Calling the Routines Generated by the Module Wizard

Although Fortran 95/90 does not support objects, it does provide Fortran 95/90 modules. A module is a set of declarations that are grouped together under a global name, and are made available to other program units by using the USE statement.

The Fortran Module Wizard generates a source file containing one or more modules. The types of information placed in the modules include:

The jacket routines make the external procedures easier to call from Fortran by handling data conversion and low-level invocation details.

The use of modules allows the Visual Fortran Module Wizard to encapsulate the data structures and procedures exposed by an object or DLL in a single place. You can then share these definitions in multiple Fortran programs.

The appropriate USE statement needs to be added in your program, as well as function invocations or subroutine calls.

The routines generated by the Visual Fortran Module Wizard are designed to be called from Fortran. These routines in turn call the appropriate system routines (not designed to be called from Fortran), thereby simplifying the coding needed to use COM and Automation objects.

Visual Fortran provides a set of run-time routines that present to the Fortran programmer a higher level abstraction of the COM and Automation functionality. The Fortran interfaces that the Wizard generates hide most of the differences between Automation objects and COM objects.

Depending on the options specified, the following routines can be present in the generated code:

DFCOM Routines (COMxxxxx)
COMAddObject Reference Adds a reference to an object's interface.
COMCLSIDFromProgID Passes a programmatic identifier and returns the corresponding class identifier.
COMCLSIDFromString Passes a class identifier string and returns the corresponding class identifier.
COMCreateObjectByGUID Passes a class identifier and creates an instance of an object. It returns a pointer to the object's interface.
COMCreateObjectByProgID Passes a programmatic identifier and creates an instance of an object. It returns a pointer to the object's IDispatch interface.
COMGetActiveObjectByGUID Pass a class identifier and returns a pointer to the interface of a currently active object.
COMGetActiveObjectByProgID Passes a programmatic identifier and returns a pointer to the IDispatch interface of a currently active object.
COMInitialize Initializes the COM library. You must initialize the library before calling any other COM or AUTO routine.
COMIsEqualGUID Determines if two GUIDs are the same.
COMGetFileObject Passes a file name and returns a pointer to the IDispatch interface of an Automation object that can manipulate the file.
COMQueryInterface Passes an interface identifier and it returns a pointer to an object's interface.
COMReleaseObject Indicates that the program is done with a reference to an object's interface.
COMStringFromGUID Passes a GUID and returns the corresponding string representation.
COMUninitialize Uninitializes the COM library. This must be the last COM routine that you call.
DFAUTO Automation Routines (AUTOxxxxx)
AUTOAddArg Passes an argument name and value and adds the argument to the argument list data structure.
AUTOAllocateInvokeArgs Allocates an argument list data structure that holds the arguments that you will pass to AUTOInvoke.
AUTODeallocateInvokeArgs Deallocates an argument list data structure.
AUTOGetExceptInfo Retrieves the exception information when a method has returned an exception status.
AUTOGetProperty Passes the name or identifier of the property and gets the value of the Automation object's property.
AUTOGetPropertyByID Passes the member ID of the property and gets the value of the Automation object's property into the argument list's first argument.
AUTOGetPropertyInvokeArgs Passes an argument list data structure and gets the value of the Automation object's property specified in the argument list's first argument.
AUTOInvoke Passes the name or identifier of an object's method and an argument list data structure. It invokes the method with the passed arguments.
AUTOSetProperty Passes the name or identifier of the property and a value. It sets the value of the Automation object's property.
AUTOSetPropertyByID Passes the member ID of the property and sets the value of the Automation object's property using the argument list's first argument.
AUTOSetPropertyInvokeArgs Passes an argument list data structure and sets the value of the Automation object's property specified in the argument list's first argument.

Visual Fortran Samples include several projects in the ...\DF98\SAMPLES\ADVANCED\COM folder that demonstrate the use of the Fortran Module Wizard. For example:

Example of Generated Code Used by the DSLINES Sample

The DLINES Sample contains the code that invokes this and other Microsoft visual development environment functionality using COM interfaces.

The following code shows an annotated version of a portion of the code generated by the Fortran Module Wizard from the COM type information in ...\Common\MSDev98\Bin\devshl.dll. This COM type information describes the top-level objects in the Microsoft visual development environment object model.

 INTERFACE
 !  Saves the document to disk.         

 INTEGER*4 FUNCTION IGenericDocument_Save($OBJECT, vFilename, &
					vBoolPrompt, pSaved)         
 USE DFWINTY
 INTEGER*4, INTENT(IN)	:: $OBJECT     ! Object Pointer

 !DEC$ ATTRIBUTES VALUE	:: $OBJECT                                   

 TYPE (VARIANT), INTENT(IN)  :: vFilename   ! (Optional Arg)         
 !DEC$ ATTRIBUTES VALUE      :: vFilename
 TYPE (VARIANT), INTENT(IN)  :: vBoolPrompt	! (Optional Arg)
 !DEC$ ATTRIBUTES VALUE      :: vBoolPrompt

 INTEGER*4, INTENT(OUT)      :: pSaved          ! Void               
 !DEC$ ATTRIBUTES REFERENCE  :: pSaved
 !DEC$ ATTRIBUTES STDCALL    :: IGenericDocument_Save
 END FUNCTION IGenericDocument_Save
 END INTERFACE

 POINTER(IGenericDocument_Save_PTR, IGenericDocument_Save) ! routine pointer 

Notes for this example:

If the type information provides a comment that describes the member function, then the comment is placed before the beginning of the procedure.

The first argument to the procedure is always $OBJECT. It is a pointer to the object's interface. The remaining argument names are determined from the type information. For information on how to get a pointer to an object's interface, see Getting a Pointer to an Object's Interface.

This is an example of an ATTRIBUTES directive statement used to specify the calling convention of an argument.

A VARIANT is a data structure that can contain any type of Automation data. It contains a field that identifies the type of data and a union that holds the data value. The use of a VARIANT argument allows the caller to use any data type that can be converted into the data type expected by the member function.

Nearly every COM member function returns a status of type HRESULT. Because of this, if a COM member function produces output it uses output arguments to return the values. In this example, the "pSaved" argument returns a routine specific status value.

The interface of a COM member function looks very similar to the interface for a dynamic link library function with one major exception. Unlike a DLL function, the address of a COM member function is never known at program link time. You must get a pointer to an object's interface at run-time, and the address of a particular member function is computed from that.


The following code shows an annotated version of the wrapper generated by the Fortran Module Wizard for the "Save" function. The name of a wrapper is the same as the name of the corresponding member function, prefixed with a "$" character.


  ! Saves the document to disk.
  INTEGER*4 FUNCTION $IGenericDocument_Save($OBJECT, vFilename, &  
					vBoolPrompt, pSaved)
  !DEC$ ATTRIBUTES DLLEXPORT	:: $IGenericDocument_Save
  IMPLICIT NONE

  INTEGER*4, INTENT(IN)	:: $OBJECT	 ! Object Pointer
  !DEC$ ATTRIBUTES VALUE	:: $OBJECT
  TYPE (VARIANT), INTENT(IN), OPTIONAL	:: vFilename
  !DEC$ ATTRIBUTES REFERENCE	:: vFilename
  TYPE (VARIANT), INTENT(IN), OPTIONAL	:: vBoolPrompt
  !DEC$ ATTRIBUTES REFERENCE	:: vBoolPrompt
  INTEGER*4, INTENT(OUT)	:: pSaved	! Void
  !DEC$ ATTRIBUTES REFERENCE	:: pSaved

  INTEGER*4 $RETURN
  INTEGER*4 $VTBL		    ! Interface Function Table    
  POINTER($VPTR, $VTBL)
  TYPE (VARIANT) :: $VAR_vFilename
  TYPE (VARIANT) :: $VAR_vBoolPrompt
  IF (PRESENT(vFilename)) THEN                                   
      $VAR_vFilename = vFilename
  ELSE
     $VAR_vFilename = OPTIONAL_VARIANT
  END IF
  IF (PRESENT(vBoolPrompt)) THEN
     $VAR_vBoolPrompt = vBoolPrompt
  ELSE
    $VAR_vBoolPrompt = OPTIONAL_VARIANT
  END IF
  $VPTR = $OBJECT		   ! Interface Function Table     
  $VPTR = $VTBL + 84	! Add routine table offset
  IGenericDocument_Save_PTR = $VTBL
  $RETURN = IGenericDocument_Save($OBJECT, $VAR_vFilename, &
  $VAR_vBoolPrompt, pSaved)
  $IGenericDocument_Save = $RETURN
  END FUNCTION $IGenericDocument_Save

Notes for this example:

The wrapper takes the same argument names as the member function interface.

The wrapper computes the address of the member function from the interface pointer and an offset found in the interface's type information. In implementation terms, an interface pointer is a pointer to a pointer to an array of function pointers called an "Interface Function Table".

Arguments to a COM or Automation routine can be optional. The wrapper handles the invocation details for specifying an optional argument that is not present in the call.

The offset of the "Save" member function is 84. The code assigns the computed address to the function pointer IGenericDocument_Save_PTR, which was declared with the interface shown above, and then calls the function.


The DLINES Sample contains the code that invokes this and other Microsoft visual development environment functionality using COM interfaces.

Example of Generated Code Used by the DSBUILD Sample

The DSBUILD example contains the code that invokes this and other Microsoft visual development environment functionality using Automation interfaces.

The following code shows an annotated version of a portion of the code generated by the Fortran Module Wizard from the Automation type information in ...\Common\MSDev98\Bin\devshl.dll.


 ! Rebuilds all files in a specified configuration.
 SUBROUTINE IApplication_RebuildAll($OBJECT, Configuration, $STATUS) 
 !DEC$ ATTRIBUTES DLLEXPORT :: IApplication_RebuildAll
 IMPLICIT NONE

 INTEGER*4, INTENT(IN)            :: $OBJECT        ! Object Pointer
 !DEC$ ATTRIBUTES VALUE           :: $OBJECT
 TYPE (VARIANT), INTENT(IN), OPTIONAL :: Configuration
 !DEC$ ATTRIBUTES REFERENCE          :: Configuration
 INTEGER*4, INTENT(OUT), OPTIONAL    :: $STATUS       ! Method status
 !DEC$ ATTRIBUTES REFERENCE          :: $STATUS
 INTEGER*4 $$STATUS
 INTEGER*4 invokeargs
 invokeargs = AUTOALLOCATEINVOKEARGS()                       
 IF (PRESENT(Configuration)) CALL AUTOADDARG(invokeargs, '$ARG1', &
					Configuration, AUTO_ARG_IN)
 $$STATUS = AUTOINVOKE($OBJECT, 28, invokeargs)              
 IF (PRESENT($STATUS)) $STATUS = $$STATUS                    
 CALL AUTODEALLOCATEINVOKEARGS (invokeargs)                  
 END SUBROUTINE IApplication_RebuildAll

Notes for this example:

The first argument to the procedure is always $OBJECT. It is a pointer to an Automation object's IDispatch interface. The last argument to the procedure is always $STATUS. It is an optional argument that you can specify if you wish to examine the return status of the method. The IDispatch Invoke member function returns a status of type HRESULT. An HRESULT is a 32-bit value. It has the same structure as a Win32 error code. In between the $OBJECT and $STATUS arguments are the method arguments' names determined from the type information. Sometimes, the type information does not provide a name for an argument. The Fortran Module Wizard creates a "$ARGn" name in this case.

AUTOAllocateInvokeArgs allocates a data structure that is used to collect the arguments that you will pass to the method. AUTOAddArg adds an argument to this data structure.

AUTOInvoke invokes the named method passing the argument list. This returns a status result.

If the caller supplied a status argument, the code copies the status result to it.

AUTODeallocateInvokeArgs deallocates the memory used by the argument list data structure.


The DSBUILD Sample in the ...\DF98\Samples\Advanced\COM\ folder contains the code that invokes this and other Microsoft visual development environment functionality using Automation interfaces.