Calling Fortran from other .NET languages
In Visual Studio a solution is formed from several projects.
For example, a solution might contain a project to create an executable and
another to create a library that is used by the executable. It is convenient to
use the terms solution and project in this sense even though
you may not be using Visual Studio.
The code for a project will usually be written in one programming language but a
different language might be used for another project in the solution. For
example a library written in Fortran might be called from an executable written
However, when mixing languages in this way, it is important to understand that
not all Fortran types have exact equivalents inside .NET. For example, the
Fortran CHARACTER type, with its fixed size and blank padding rules is not the
same as a .NET string (which incidently also caters for UNICODE characters).
Also Fortran multi-dimensional arrays are stored in a different order (i.e.
column major order) and Fortran arrays are not necessarily zero based.
If your intention is to have a main program written in (say) C# and call an FTN95
DLL then it is important you tag the C# application as 32-bit. If you do not do this
then on 64-bit operating systems the C# application may get JIT compiled in 64-bit mode.
When a call is made to the FTN95 DLL then it will fail to JIT because it will force
32-bit mode. The result will be a program ending exception.
The linker DBK_LINK or DBK_LINK2 is used to link code produced by one or more
calls to the FTN95 compiler. Calls to DBK_LINK or DBK_LINK2 are made a) during
Visual Studio build processes, b) when DBK_LINK or DBK_LINK2 is used on a
command line, and c) when FTN95 is called using /LINK or /LGO. DBK_LINK creates
a file which is known as an assembly. The assembly file can have a .EXE or .DLL
extension, and in the latter case it can be called by other software.
When you want a particular FTN95 routine to be callable from other .NET
languages you can include an ASSEMBLY_INTERFACE directive in the FTN95 code.
This directs the compiler to create a stub that can be used in a call to the
routine from another language. The purpose of the stub is to resolve the
differences that arise when a Fortran type is not compatible with its .NET
equivalent. For example:
The resulting Fortran name for the routine will use only upper case letters
(even when lower case letters are used in the code). In contrast, the external
name (MyCalculation) is case sensitive.
Consider the following example:
and suppose that the name of the resulting DLL is MyLib.dll.
CALC would be callable by the following C# fragment:
You can use "Calc" instead of "MyCalc" as the interface name when calling
from C# but not when calling from Visual Basic.
For Visual Basic, the interface name, when converted to upper case, must not
be the same as the Fortran name of the subprogram.
You can think of the name MyCalc as a synonym for CALC but when MyCalc is called
from other .NET languages, the following argument transformations are
1. Fortran arrays are mapped to .NET arrays. The (column major) ordering is not
changed because this transformation would be expensive for large arrays. Your
code must allow for this difference. Thus the C# array element c[1,2] becomes
C(2,1) in Fortran. Arrays are passed by reference.
2. Fortran CHARACTERs are mapped to System.String objects and passed by value
(this means that changes made to a dummy argument are not passed back to the
actual argument at the point of call).
3. Scalar INTEGER and REAL values are passed by value unless INTENT(OUT) or
INTENT(INOUT) is used in which case the argument is passed by reference.
4. All other arguments, including objects (i.e. instances of a class, see
.NET Objects), are passed by reference.
These transformations greatly simplify the calling of Fortran from other .NET
The use of an ASSEMBLY_INTERFACE is not necessary when all of the arguments are
scalar INTEGERs or REALs. However, the call (from C# say) must stipulate that
all of the arguments are passed as 'unsafe' pointer types (using 'fixed' if
necessary) and the name of the routine (in C#) must not use lower case letters.
It is simpler if you use an array index with a lower bound of zero when you
declare Fortran array arguments. This makes them consistent with C# arrays.
However, you can use a different lower bound. For example, if you declared a
two-dimensional Fortran array with both indexes starting at 1 by using say
C(:,:), then the C# element c[0,1] would map to C(2,1) (i.e. both indexes are
increased by one and their order is reversed).
A C# string is converted into the corresponding Fortran CHARACTER string and any
Unicode characters that cannot be represented in ASCII form are replaced
according to the rules of System.Text.Encoding.Default. Any changes made to the
string from within the Fortran code are not reflected back to the C# caller.
.NET objects (such as .NET strings and .NET arrays) are passed to your Fortran
code without transformation. Passing objects avoids the overhead incurred when
using the standard transformations and the resulting flexibilty can sometimes
be used to resolve complex interfacing problems.
Note that, in a FTN95 program, you cannot declare a Fortran array whose elements
are .NET objects. Such arrays can only be passed as .NET arrays from another
You can use the FTN95 complex number classes in C# and Visual Basic .NET. These
are defined in ftn95lib.dll with the namespace Salford.Fortran.
The class names are Complex8 (for single precision) and Complex16 (for double
precision) and the public data members in both classes are
called Real and Imaginary. Objects of these types can be passed to and
from a Fortran DLL. Here is some sample C# code.
Salford.Fortran.Complex16 x = new