Writing a Wrapper Module to Call the Fortran Function

The mechanism by which an IMLPlus program calls a Fortran function within a DLL is the DllFunction class. The general procedure for using the DllFunction class is as follows:

  1. Create an object of type DllFunction.
  2. Call the Init method of the DllFunction class. The Init method specifies the filename of the DLL, the name of the function to be called within the DLL, and the number of parameters the function expects.
  3. Specify the type and value of each function parameter by calling the NextArgIs methods of the DllFunction class.
  4. Perform the actual function call by calling one of the Call_ methods of the DllFunction class.

Because of the number of programming statements required to use the DllFunction class, it is usually best to write an IML module to encapsulate access to a Fortran function.

IML Studio is distributed with a sample program that defines a wrapper module that encapsulates access to the example function My_Fortran_Function. The sample program is called Demo_My_Fortran_Function.sx and is stored in the subdirectory

<IMLStudio>\Programs\Samples\User Extensions

where <IMLStudio> is the directory in which you installed IML Studio. The program defines the following wrapper module called My_Fortran_Function:

/* Wrapper module to call the Fortran function "My_Fortran_Function"
   exported from the DLL "My_Fortran_Functions.dll".
   The Fortran function computes the simple product of a scalar with
   a vector: y = c * x
   Module Inputs:
        double c   a scalar
        Matrix x   an (n x 1) matrix (that is, a column vector)
   Module Outputs:
        returns an (n x 1) matrix y such that y = c * x
*/
start My_Fortran_Function( double c, x );
    declare int nRows = nrow(x);
    declare double[] adY = new double[nRows];

    declare String sPathName; /* location of DLL */
    sPathName = "My_Fortran_Functions.dll";
    declare String sFuncName; /* name of function in DLL */
    sFuncName = "my_fortran_function"; /* may be different from the Fortran name */

    declare DllFunction func = new DllFunction();
    func.Init( sPathName, sFuncName, 4 ); /* 4 parameters */
    func.NextArgIsInt32( nRows ); /* int32 = integer(4) */
    func.NextArgIsDouble( c );    /* double = real(8)   */
    func.NextArgIsDoubleArray( x );
    func.NextArgIsDoubleArray( adY );

    /* call function and get the return value */
    declare int nReturnValue;
    nReturnValue = func.Call_Int32();
    if nReturnValue != 0 then do;
        print "The Fortran function returned an error code.";
        abort;
        end;
    return ( adY );
finish;

The module takes two parameters: a scalar constant c, and a matrix x. An explanation of the module's statements follows:

  1. The module defines an int variable called nRows that specifies the number of rows in the x vector.
  2. The module creates an array of type double to contain the output vector computed by the Fortran function.
  3. The module defines a String object to contain the complete pathname of the DLL containing the Fortran function.
  4. The module defines a String object to contain the exported name of the Fortran function. The name used here may need to be different from the name appearing in the Fortran source code. The steps necessary to discover the actual exported name of a function are described in Packaging a Fortran Function within a DLL.
  5. The module creates an object of the DllFunction class.
  6. The module calls the Init method of the DllFunction class and specifies that the Fortran function requires 4 parameters.
  7. The module calls the method NextArgIsInt32 of the DllFunction class to specify that the first function parameter is a 32-bit integer with the value of the nRows variable. The Fortran type INTEGER(4) is 32 bits wide.
  8. The module calls the method NextArgIsDouble of the DllFunction class to specify that the second function parameter is a double-precision floating-point number with the value of the c variable. The Fortran type REAL(8) corresponds to the C/Java type double.
  9. The module calls the method NextArgIsDoubleArray of the DllFunction class to specify that the third function parameter is an array of double-precision floating-point numbers. The x variable's data is passed by reference to the Fortran function.
  10. The module calls the method NextArgIsDoubleArray of the DllFunction class to specify that the fourth function parameter is an array of double-precision floating-point numbers. The adY variable's data is passed by reference to the Fortran function.
  11. The module defines an int variable to hold the return value from the Fortran function.
  12. The module calls the method Call_Int32 of the DllFunction class and assigns the 32-bit integer return value from the Fortran function to the nReturnValue variable.
  13. The module checks the nReturnValue variable to see if the Fortran function returned a non-zero value, which indicates that an error occurred. If an error occurred, the module aborts the program.
  14. The module returns the adY variable as the module's return value. IMLPlus automatically converts the double array data type to the matrix data type returned from all function modules.