All SIDL methods are implemented as FORTRAN 90 subroutines regardless of whether they have a return value or not. For object methods, the object or interface pointer is passed as the first argument to the subroutine before all the formally declared arguments. The exception is static methods, where the object or interface pointer does not appear in the argument list at all.
When a method has a return value, a variable to hold the return value should be passed as an argument following the formally declared arguments. When a method can throw an exception (i.e., its SIDL definition has a throws clause), a variable of type type(SIDL_Base_Exception_t) should be passed to hold a SIDL.BaseException pointer if an exception is thrown. The exception argument appears after the return value when both occur in a method. After the call, the client should test this argument using is_null or not_null. If it is not_null, an exception was thrown by the method, and the method should respond appropriately. When an exception is thrown, the value of all other arguments is undefined, and the best couse of action is to ignore their values.
The name of the module that holds the method definitions is derived from the fully qualified name of the class or interface. You can generate the module name by replacing all the periods with underscores. For example, the methods for SIDL.BaseException are defined in a module named SIDL_BaseException in the file SIDL_BaseException.F90. The name of the module holding the derived type of the class or interface is the same as the one holding the methods except that it has _type appended to it. The types for SIDL.BaseException are called SIDL_BaseException_t and SIDL_BaseException_a, for the array, and they are defined in the file SIDL_BaseException_type.F90.
The name of the subroutine that FORTRAN 90 clients is the method's full name from the SIDL description. If the method is specified as overloaded (i.e., has a name extension), the method's full name will be used. That is, the concatenation of the short name and the name extension will be used for a unique method name.
For example, to call the deleteRef() method on a SIDL.BaseInterface interface, you would write:
use SIDL_BaseInterface type(SIDL_BaseInterface_t) :: interface1, interface2 logical :: areSame ! ! code to initialize interface1 & interface 2 here ! call deleteRef(interface1)
To call the isSame method on a SIDL.BaseInterface, you would write:
use SIDL_BaseInterface ! later in the code call isSame(interface1, interface2, areSame) ! areSame holds the return value
To call the queryInt method on a SIDL.BaseInterface, you would write:
use SIDL_BaseInterface ! later call queryInt(interface1, 'My.Interface.Name', interface2) ! interface2 holds the return value now
Examples of calls to SIDL overloaded methods are based on the overload_sample.sidl file shown in Section 3.6. Recall that the file describes three versions of the getValue method. The first takes no arguments, the second takes an integer argument, and the third takes a boolean. Each is called in the code snippet below:
use Overload_Sample type(Overload_Sample_t) :: t logical :: b1, bretval integer (selected_int_kind(9)) :: i1, iretval call new(t) call getValue (t, iretval) call getValueInt (t, i1, iretval) call getValueBool (t, b1, bretval)
For interfaces and classes, there is an implicit method called cast(). There are actually a set of overloaded methods that support every allowable cast between a type an all its parent types (objects and interfaces). The first argument is the object/interface to be cast, and the second argument is a variable of the desired type. If the value of the second argument after the call is not_null, the cast was successful; otherwise, the cast failed. cast() is similar to the queryInt method in SIDL.BaseInterface except it does not increment the reference count of the return object or interface, and it may return an object or an interface pointer. The queryInt() method always returns an interface pointer.
For non-abstract classes, there is an implicit method called new(). It creates and returns an instance of the class.
Here are examples of the use of these two methods:
use SIDL_BaseClass use SIDL_BaseInterface type(SIDL_BaseClass_t) :: object type(SIDL_BaseInterface_t) :: interface ! perhaps other code here call new(object) call cast(object, interface)
Here is an example call to the addSearchPath(), a static method, in the SIDL.Loader class:
use SIDL_Loader ! later call addSearchPath('/try/looking/here')
Your FORTRAN 90 must manage any object references created by the calls you make.
Here is another example adapted from the Babel regression tests. Package ExceptionTest has a class named Fib with a method declared in SIDL as follows:
int getFib(in int n, in int max_depth, in int max_value, in int depth) throws NegativeValueException, FibException;
Here is the outline of a FORTRAN 90 code fragment to use this method.
use ExceptionTest_Fib use ExceptionTest_FibException use ExceptionTest_NegativeValueException use SIDL_BaseException type(ExceptionTest_Fib_t) :: fib type(SIDL_BaseException_t) :: except type(ExceptionTest_FibException_t) :: fibexcept type(ExceptionTest_NegativeValueException_t) :: nvexcept integer (selected_int_kind(9)) :: index, maxdepth, maxval, depth, result call new(fib) index = 4 maxdepth = 100 maxvalue = 32000 depth = 0 call getFib(fib, index, maxdepth, maxvalue, depth, result, except) if (not_null(except)) then call cast(except, fibexcept) if (not_null(except2)) then ! do something here with the FibException else call cast(except, nvexcept) ! do something here with the NegativeValueException endif call deleteRef(except) else write (*,*) 'getFib for ', index, ' returned ', result endif call deleteRef(fib)
Here is an example of what Babel will produce for an enumerated type with some of the whitespace and comments reduced for brevity.
! File: enums_car.F90 ! Symbol: enums.car-v1.0 ! Symbol Type: enumeration ! Babel Version: 0.8.2 ! Description: Client-side module for enums.car module enums_car ! Symbol "enums.car" (version 1.0) integer (selected_int_kind(9)), parameter :: porsche = 911 integer (selected_int_kind(9)), parameter :: ford = 150 integer (selected_int_kind(9)), parameter :: mercedes = 550 end module enums_car
Here is how you should invoke Babel to create the FORTRAN 90 stubs for an IDL file 10.1.
% babel -client=f90 file.sidlor simply
% babel -c=f90 file.sidl
This will create a babel.make file, numerous C headers, numerous C source files, and some FORTRAN 90 files. The files ending in _fStub.c are called by the FORTRAN 90 module which in turn allow FORTRAN 90 to call a SIDL method. The files ending in _type.F90 contain derived type definitions for classes and interfaces., and the other files ending in .F90 are FORTRAN 90 modules containing methods.
You will need to compile and link the files ending in _fStub.c (i.e., STUBSRCS in babel.make) and all the files ending in .F90 (i.e., STUBMODULESRCS and TYPEMODULESRCS in babel.make) into your application. Normally, the IOR files (_IOR.c) are linked together with the implementation file, so you probably don't need to compile them.