When calling a Visual Fortran DLL from Visual Basic, important argument passing and data type considerations are:
This section discusses the following topics:
Declaring the Fortran Routine in Visual Basic
When you declare a Fortran routine in Basic the routine name is exported in exactly the same case as you declared it. Optionally, you can specify a directory path to the Fortran DLL in the declaration.
The following Visual Basic example declares a Fortran subroutine named FortranCall that takes two single-precision arguments: Declare Sub FortranCall Lib "d:\MyProjects\FCall.dll" (A1 as Single,
A2 as Single)
The following example declares a Fortran function named FortranFunc that
takes two integer (32-bit) arguments and returns a single precision value:
Declare Function FortranFunc Lib "d:\MyProject\FFun.dll" (A1 as Long,
A2 as Long)
As Single
Exporting the Routine from the Fortran DLL
When you create the Fortran DLL, you need to add two additional attributes to the function or subroutine declaration so that it can be accessed from outside the DLL.
The Fortran routine name must be exported from the DLL, and it must be aliased to match exactly the name expected by Basic. The ATTRIBUTES (cDEC$ ATTRIBUTES compiler directive) and ALIAS declarations export the name and alias, as shown below for a Fortran subroutine: SUBROUTINE FortranCall
!DEC$ ATTRIBUTES DLLEXPORT :: FortranCall ! This exports the name
!DEC$ ATTRIBUTES ALIAS : "FortranCall" :: FortranCall !This sets it
This is also true for Fortran functions, which must be exported and aliased to match exactly the name
expected by Basic:
REAL Function FortranFunc
!DEC$ ATTRIBUTES DLLEXPORT :: FortranFunc
!DEC$ ATTRIBUTES ALIAS : "FortranFunc" :: FortranFunc
When you pass data between Visual Basic and Visual Fortran, you need to keep in mind the calling standard used by the two languages, the size of the data, and the on-disk format of the data.
The following table summaries the calling considerations for the data types:
Data Type | Calling Considerations |
---|---|
Integer | By default, both Visual Basic and Visual Fortran pass integers by reference. The default integer size in Basic is 2 bytes, equivalent to INTEGER(2) in Fortran. No extra action is required by either language to access integer arguments. |
Floating point | By default, both Visual Basic and Visual Fortran pass single- and double-precision floating point numbers by reference. The size of a single-precision floating point number is 4 bytes in both languages. The size of a double-precision floating point number is 8 bytes in both languages. No extra action is required by either language to access floating point arguments. |
Logical | By default, both Basic and Fortran pass logical data by reference. The default logical size in Basic is two bytes, equivalent to LOGICAL(2) in Fortran. No extra action is required by either language to access logical arguments. |
Strings | By default, Basic passes strings in a structure
called a BSTR. By default, Fortran passes strings in two arguments: the string's address and a
hidden argument containing the string's length. These defaults can be easily overridden by
making changes in the Basic declaration, and sometimes in the Fortran declaration too.
Whenever you pass a string from Basic to Fortran, the passing mechanism should be declared as ByVal. See the String Passing Examples. |
Arrays | By default, Basic arrays are 0-based. Fortran
arrays are 1-based by default. When you declare a Basic array to be of size n,
n+1 elements are allocated, including the 0th element. This can be overridden, as
show in the Array Passing Examples.
To pass arrays of numbers from Basic to Fortran, whether they are integer or floating-point numbers, pass the first element. In the Fortran code declare the argument to be an array. Usually the Basic code will pass the number of elements in the array. To pass arrays of strings or types from Basic to Fortran requires the use of COM utilities to read the structures created by Basic. The arrays are passed as is from Basic, and then extracted in the Fortran code using SafeArrayxx utilities. For more detail, please refer to the Visual Fortran Samples found in the MixLang\VB\arrays and MixLang\VB\typearrays folders. |
Types | Basic-declared types can be passed from Basic to
Fortran. The Basic-declared type will also have to be declared in Fortran; care should be taken
to keep the two structures the same. In Fortran, the TYPE should
be declared to be packed, usually PACK:2. You should be aware of the
default sizes of the TYPE elements in the two languages, and adjust the
defaults accordingly.
Note that strings in Basic-declared types are stored as Unicode, which can be declared in Fortran as an array of Integer*2. To access these strings from Fortran, use the Natural Language System (NLS) API calls. For information, see Using National Language Support Routines and the Visual Fortran Samples found in the MixLang\VB\typearrays folder. |
The following example shows passing strings using the usual case, where the string will have varying length, and the length must also be passed to Fortran ByVal:
Visual Basic code:
Declare Sub FortString1 Lib "forttest" (ByVal S1 as String,
ByVal L1 as Long)
Dim S1 as String * 12
Call FortString1(S1, Len(S1))
Visual Fortran code:
Subroutine FortString1 (mystring)
!DEC$ ATTRIBUTES DLLEXPORT, ALIAS : "FortString1" :: FortString1
CHARACTER*(*) mystring
The following example shows shows passing strings where the length of the string will be constant and known by both the Basic and Fortran code, so you do not need to pass the length to Fortran, but you need to tell Fortran not to expect its length:
Visual Basic code:
Declare Sub FortString2 Lib "forttest" (ByVal S2 as String)
Dim S2 as String * 25
Visual Fortran code:
Subroutine FortString2 (mystring)
!DEC$ ATTRIBUTES DLLEXPORT, ALIAS : "FortString2" :: FortString2
!DEC$ ATTRIBUTES REFERENCE :: mystring
CHARACTER*25 mystring
The following example shows shows passing arrays:
Visual Basic code:
Basic declaration:
Declare Sub FortArray1 Lib "forttest" (A1 as Long, NumElem as long)
Dim A1(1:3) as Long
Call FortArray1(A1(1), 3)
Visual Fortran code:
Subroutine FortArray1 (Array1, N)
!DEC$ ATTRIBUTES DLLEXPORT, ALIAS : "FortArray1" :: FortArray1
Integer array1(N)