next up previous contents
Next: Implementing Classes in FORTRAN Up: FORTRAN 90 Bindings Previous: Basic Types   Contents

Calling Methods From FORTRAN 90

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.sidl
or 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.


next up previous contents
Next: Implementing Classes in FORTRAN Up: FORTRAN 90 Bindings Previous: Basic Types   Contents


babel-0.8.6
users_guide Last Modified 2003-07-09

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