Just note that, the example is more than a simple call back. The C# actually calls a Fortran function in a dll. Within the Fortran function calls the callback in C#.
--- Fortran code -----
module f90Callback
contains
subroutine func1(iArr, progressCllBak)
!DEC$ ATTRIBUTES DLLEXPORT ::func1
!DEC$ ATTRIBUTES REFERENCE :: iArr, progressCllBak
implicit none
external progressCllBak
integer :: iCB
integer, INTENT(OUT) :: iArr(2)
! Variables
! Body of f90Callback
print *, "Hello Before"
iCB = 3
iArr(1) = 5
iArr(2) = 7
call progressCllBak(iCB)
print *, "setting callback value in Fortran as :", iCB
print *, "Hello After"
return
end subroutine func1
end module f90Callback
------- C# code ---------
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace CScallbackDriver
{
class Program
{
// 0. Define a counter for the Progress callback to update
public int localCounter;
// 1. Define delegate type
[UnmanagedFunctionPointer(CallingConvention=CallingConvention.Cdecl)]
public delegate void dgateInt(ref int numYears);
// 2. Create a delegate variable
public dgateInt dg_progCB;
public Program() {
// 3. Instantiate delegate, typically in a Constructor of the class
dg_progCB = new dgateInt(onUpdateProgress);
}
// 4. Define the c# callback function
public void onUpdateProgress(ref int progCount) {
localCounter = progCount;
}
int iArg;
static void Main(string[] args)
{
Program myProg = new Program();
myProg.localCounter = 0;
int[] iArrB = new int[2];
//6. Call normal Fortran function from DLL, and passing the callback delegate
func1(ref iArrB[0], myProg.dg_progCB);
Console.WriteLine("Retrieve callback value as {0}", myProg.localCounter);
Console.ReadKey();
}
// 5. Define the dll interface
[DllImport("f90Callback", EntryPoint="F90CALLBACK_mp_FUNC1", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
public static extern void func1([In, Out] ref int iArr, [MarshalAs(UnmanagedType.FunctionPtr)] dgateInt blah);
}
}