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 -server=f90 file.sidlor simply
% babel -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 extra 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 use statements here..." 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 the implementation here..." comment.
! DO-NOT-DELETE splicer.begin(_miscellaneous_code_start) ! Insert extra code here... ! DO-NOT-DELETE splicer.end(_miscellaneous_code_start) . . . subroutine Pkg_Class_name_mi(args) ! DO-NOT-DELETE splicer.begin(Pkg.Class.name.use) ! Insert use statements here... ! DO-NOT_DELETE splicer.end(Pkg.Class.name.use) implicit none integer (selected_int_kind(18)) :: arg ! DO-NOT-DELETE splicer.begin(Pkg.Class.name) ! Insert the implementation here... ! DO-NOT-DELETE splicer.end(Pkg.Class.name)
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 type sort_SimpleCounter_private sequence ! DO-NOT-DELETE splicer.begin(sort.SimpleCounter.private_data) integer(selected_int_kind(9)) :: count ! DO-NOT-DELETE splicer.end(sort.SimpleCounter.private_data) end type sort_SimpleCounter_private type sort_SimpleCounter_wrap sequence type(sort_SimpleCounter_private), 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) use sort_SimpleCounter use sort_SimpleCounter_private ! DO-NOT-DELETE splicer.begin(sort.SimpleCounter._ctor.use) ! DO-NOT-DELETE splicer.end(sort.SimpleCounter._ctor.use) implicit none type(sort_SimpleCounter_t) :: self ! 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) use sort_SimpleCounter use sort_SimpleCounter_private ! DO-NOT-DELETE splicer.begin(sort.SimpleCounter._dtor.use) ! DO-NOT-DELETE splicer.end(sort.SimpleCounter._dtor.use) implicit none type(sort_SimpleCounter_t) :: self ! 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