This page is named “CSharp Interoperability” instead of “C# Interoperability” due to restrictions on special characters in page names.
C# is able to call Fortran DLLs using P/Invoke.
See How to Call Fortran DLLs from C# or CSharpFortran for full examples with source code.
The following example shows how to call an Intel Fortran 12.1 DLL using a C# console application. The DLL function also features a simple call back function so that the C# application can display the progress of the Fortran method to the user. The example was adapted from xTechNotes. See also Calling FORTRAN function or subroutine in DLL from C# code
First, create a Dynamic-link Library project in Intel Fortran. The DoWork function passes a 2-D array of known size. The contents of the array are modified in the method.
Make sure to add a post-build event to copy the DLL to the C# application directory:
copy $(ProjectDir)\Debug\$(TargetName).dll $(SolutionDir)\CSharpClient\bin\Debug
Code of the module:
module FortranCallBack
implicit none
contains
subroutine DoWork(n, A, progressCallBack)
!DEC$ ATTRIBUTES DLLEXPORT :: DoWork
!DEC$ ATTRIBUTES ALIAS: 'DoWork' :: DoWork
!DEC$ ATTRIBUTES REFERENCE :: n, A, progressCallBack
external progressCallBack
integer, intent(in) :: n
real(8), dimension(n, n), intent(inout) :: A
integer :: i
do i = 1, n
write (*,*) "Fortran says: ", i
call progressCallBack(i)
A(i, i) = i**2
end do
return
end subroutine
end module
Next, make a C# console application named CSharpClient. Copy and pasted the code into the Program class.
A common mistake is failing pass the parameters to the DLL by reference (ref). Failing to do so will usually cause memory access violations.
Also make sure that you get the name of the Fortran DLL method correct. In the Fortran code we used the ALIAS attribute to override any Fortran compiler name mangling. You can verify the name of the DLL method using the DUMPBIN utility included with Visual Studio. To use DUMPBIN, open the Visual Studio Command Prompt and type DUMPBIN /EXPORTS [filename.dll].
You can step into the Fortran DLL while debugging. In the C# project properties page, go to Debug and select Enable unmanaged code debugging.
Strings can be passed from C# to Fortran using character arrays (char[]
). When converting C# strings to character arrays make sure that any unused characters are initialized to blanks.
using System;
using System.Runtime.InteropServices;
namespace CSharpClient
{
class Program
{
// Delegate type.
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void ActionRefInt(ref int progress); // Important the int is passed by ref (else we could use built-in Action<T> instead of delegate).
// Delegate variable.
public ActionRefInt callbackHandler;
public Program()
{
callbackHandler = new ActionRefInt(OnUpdateProgress);
}
static void Main(string[] args)
{
Program myProg = new Program();
int n = 10;
var A = new double[n, n];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
A[i, j] = 0.0;
}
}
DoWork(ref n, A, myProg.callbackHandler);
for (int i = 0; i < n; i++) Console.WriteLine("A(" + (i + 1) + ", " + (i + 1) + ") = " + A[i, i]);
}
public void OnUpdateProgress(ref int progress)
{
Console.WriteLine("C# says: " + progress);
}
// Fortran DLL interface.
[DllImport("FortranCallBack.dll", EntryPoint = "DoWork", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern void DoWork(ref int n, [In, Out] double[,] A, [MarshalAs(UnmanagedType.FunctionPtr)] ActionRefInt callBack);
}
}