Implementing Classes in FORTRAN 90

Much of the information from the previous section is pertinent to implementing a SIDL class in FORTRAN 90. The types of the arguments are as indicated in Table 9.1. Your implementation can call other SIDL methods in which case follow the rules for client calls.

You should invoke Babel:

% babel -exclude-external -server=f90 file.sidl
or simply
% babel -E -s=f90 file.sidl

This will create a babel.make, numerous C headers, numerous C source files and some FORTRAN 90 source files. Your job is to fill in the FORTRAN 90 source files with the implementation of the methods. The files you need to edit all end with _Impl.F90 and _Mod.F90. All your changes to the file should be made between code splicer pairs. Code between splicer pairs is retained by subsequent invocations of Babel; code outside splicer pairs is not.

Here is an example of the standard code splicer pairs in generated FORTRAN 90 code. You would replace the comment ``Insert-Code-Here'' associated with the ``miscellaneous code start'' splicer pair with code needed for your implementation such as additional abbreviation file(s) and any local, or private, subroutines. For the subroutine's ``use'' splicer pair, you would replace the ``Insert-Code-Here {Pkg.Class.name.use} (use statements)'' comment with any use statements that are needed by the subroutine. Finally, you would add the implementation between the subroutine body's splicer pairs in the place of the ``Insert-Code-Here {Pkg.Class.name} (name method)'' comment.


! DO-NOT-DELETE splicer.begin(_miscellaneous_code_start)
! Insert-Code-Here {_miscellaneous_code_start} (extra code)
! DO-NOT-DELETE splicer.end(_miscellaneous_code_start)

.
.
.

recursive subroutine Pkg_Class_name_mi(self, arg, exception)
  use sidl
  use sidl_BaseInterface
  use sidl_RuntimeException
  use Pkg_Class
  use Pkg_Class_impl
  ! DO-NOT-DELETE splicer.begin(Pkg.Class.name.use)
  ! Insert-Code-Here {Pkg.Class.name.use} (use statements)
  ! DO-NOT-DELETE splicer.end(Pkg.Class.name.use)
  implicit none
  type(Pkg_Class_t) :: self ! in
  integer (kind=sidl_int) :: arg ! in
  type(sidl_BaseInterface_t) :: exception ! out

! DO-NOT-DELETE splicer.begin(Pkg.Class.name)
! Insert-Code-Here {Pkg.Class.name} (name method)
! DO-NOT-DELETE splicer.end(Pkg.Class.name)
end subroutine Pkg_Class_name_mi

Each _Impl.F90 file contains numerous partially implemented subroutines. The SUBROUTINE and END SUBROUTINE statements have been generated and the types of the arguments declared. As mentioned above, you must provide any needed use statements and the body of each subroutine to implement the expected behavior of the method.

There are two implicit methods (i.e., methods that did not appear in the SIDL file) that must also be implemented if the object is to have state (i.e., data associated with the instance). The _ctor() method is a constructor function that is run whenever an object is created. The _dtor() method is a destructor function that is run whenever an object is destroyed. If there is not state then these functions are typically empty.

The SIDL IOR keeps a pointer for each object that is intended to hold a pointer to the object's internal data. The FORTRAN 90 skeleton provides two functions that the FORTRAN 90 developer will need to use to access the private pointer. The name of the function is derived from the fully qualified type name by replacing periods with underscores and appending __get_data_m or __set_data_m. The first argument is the object pointer (i.e., self), and the second is a derived type defined in the _Mod.F90 file. Here is an excerpt from a _Mod.F90 file for an object whose state requires a single integer value.


#include "sort_SimpleCounter_fAbbrev.h"
module sort_SimpleCounter_impl

! DO-NOT-DELETE splicer.begin(sort.SimpleCounter.use)
use sidl
! DO-NOT-DELETE splicer.end(sort.SimpleCounter.use)

type sort_SimpleCounter_priv
  sequence
  ! DO-NOT-DELETE splicer.begin(sort.SimpleCounter.private_data)
   integer(kind=sidl_int) :: count
  ! DO-NOT-DELETE splicer.end(sort.SimpleCounter.private_data)
end type sort_SimpleCounter_priv

type sort_SimpleCounter_wrap
  sequence
  type(sort_SimpleCounter_priv), pointer :: d_private_data
end type sort_SimpleCounter_wrap

end module sort_SimpleCounter_impl

The derived type sort_SimpleCounter_private is the type where the developer adds data to store the object's state, and sort_SimpleCounter_wrap exists simply to facilitate transferring the pointer to a
sort_SimpleCounter_private to and from the IOR.

Typically for a class with state, the developer needs to allocate(pd%d_private_data) in the constructor, _ctor, and deallocate(pd%d_private_data) in the destructor, _dtor. Here is a concrete example of a constructor.


recursive subroutine sort_SimpleCounter__ctor_mi(self, exception)
  use sidl
  use sidl_BaseInterface
  use sidl_RuntimeException
  use sort_SimpleCounter
  use sort_SimpleCounter_impl
  ! DO-NOT-DELETE splicer.begin(sort.SimpleCounter._ctor.use)
  ! Insert-Code-Here {sort.SimpleCounter._ctor.use} (use statements)
  ! DO-NOT-DELETE splicer.end(sort.SimpleCounter._ctor.use)
  implicit none
  type(sort_SimpleCounter_t) :: self ! in
  type(sidl_BaseInterface_t) :: exception ! out

! DO-NOT-DELETE splicer.begin(sort.SimpleCounter._ctor)
  type(sort_SimpleCounter_wrap) :: dp
  allocate(dp%d_private_data)
  dp%d_private_data%count = 0
  call sort_SimpleCounter__set_data_m(self, dp)
! DO-NOT-DELETE splicer.end(sort.SimpleCounter._ctor)
end subroutine sort_SimpleCounter__ctor_mi

Here is the corresponding destructor.


recursive subroutine sort_SimpleCounter__dtor_mi(self, exception)
  use sidl
  use sidl_BaseInterface
  use sidl_RuntimeException
  use sort_SimpleCounter
  use sort_SimpleCounter_impl
  ! DO-NOT-DELETE splicer.begin(sort.SimpleCounter._dtor.use)
  ! Insert-Code-Here {sort.SimpleCounter._dtor.use} (use statements)
  ! DO-NOT-DELETE splicer.end(sort.SimpleCounter._dtor.use)
  implicit none
  type(sort_SimpleCounter_t) :: self ! in
  type(sidl_BaseInterface_t) :: exception ! out

! DO-NOT-DELETE splicer.begin(sort.SimpleCounter._dtor)
  type(sort_SimpleCounter_wrap) :: dp
  call sort_SimpleCounter__get_data_m(self, dp)
  deallocate(dp%d_private_data)
! DO-NOT-DELETE splicer.end(sort.SimpleCounter._dtor)
end subroutine sort_SimpleCounter__dtor_mi



babel-0.11.0
users_guide Last Modified 2005-12-20

http://www.llnl.gov/CASC/components
components@llnl.gov