Topic: Calling Fortran from C#
I recently received a request from a user to provide an example of calling Fortran code from a C# program. This procedure is similar to calling Fortran with modern Visual Basic implementations. For this example, we can work with a 32-bit example. Starting with a simple Fortran subroutine:
subroutine timestwo(x, n)
use iso_c_binding
implicit none
!GCC$ ATTRIBUTES dllexport, stdcall :: timestwo
real(kind=c_double), intent(inout), dimension(n)::x
integer(kind=c_int), value::n
x = 2*x
end subroutine timestwo
In the Fortran code, the subroutine has two attributes assigned, dllexport and stdcall. The former instructs the compiler that this subroutine will be a public DLL function, and the latter specifies the calling convention. This code can be compiled as a 32-bit "Shared Library" project in Simply Fortran.
The C# code is relatively straightforward as well:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace callf
{
class Program
{
[DllImport("timestwo.dll", EntryPoint=@"timestwo@8", CallingConvention=CallingConvention.StdCall)]
static extern void timestwo(double[] x, int n);
static void Main(string[] args)
{
double[] values = new double[] { 1.0, 3.0, 5.0, 7.0, 9.0 };
timestwo(values, values.Length);
foreach(double x in values) {
System.Console.WriteLine(x);
}
System.Console.ReadKey();
}
}
}
The oddest part is the "DllImport" statement. In this example, we need to specify two extra bits of information to our "DllImport" statement in order to call our "timestwo" subroutine. First, we need to specify the decorated name of the DLL function. If one opens the resultant DLL compiled with Simply Fortran, the editor will list functions in the DLL, once of which will appear similar to:
66781460 T _timestwo@8
The "EntryPoint" argument to "DllImport" needs to reflect part of the decoration, namely the "@8" portion. Much of the confusion surrounding decorations will actually disappear if a 64-bit DLL is used instead.
The above code will actually run fine as long as the Fortran DLL is in a proper directory. For simplicity, it should be located in the same directory as the C# executable itself.
This post is just a simple example of calling Fortran from C#.
Approximatrix, LLC