Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
28630 Discussions

Calling a function defined in a C# exe from a Fortran dll

Michael_Roberts
New Contributor I
868 Views

Hi, 

Appologies if this is a duplicate - I've done a few searches and cannot quite find what I'm looking for... I'm hoping someone here can help me to do this in a "best practise" way using the Fortran/C interop. 

Basically I have a "number cruching" dll written in using Intel Fortran which runs under a C# front end. As this could take some time I would like the dll to be able to call back the exe to inform it of its current progress. 

The basic calling procedure I envisage is:

  1. C# passes Fortran the memory address of the C# routine to call in the exe when progress has changed (as a delegate?)
  2. Fortran dll updates a module procedure pointer to point to this C# routine so that it can call it later on
  3. C# starts the main fortran "DoWork" function
  4. At intermediate points in "DoWork" the C# routine is called via the pointer and C# can update the display

If anyone could point me in the right direction, or even post a small complete code - (a simple console app which passes something like an int back) I would be very greatful. 

Cheers,

Michael

0 Kudos
5 Replies
FortranFan
Honored Contributor III
868 Views

Michael,

See if the attached is of any help,

 

 

0 Kudos
Michael_Roberts
New Contributor I
868 Views

Thank you - this was a huge help. I've now successfully got this working.

The only amendment to your suggested route was the Fortran declaration when passing the delegate. When this was given the pointer attribute I was getting memory corruption, however by defining it simply as "PROCEDURE(xxx)" (no pointer or intent attributes) the problem seems to have been solved. The module pointer can then be assigned using "=>". 

I've shown my C# and Fortran below, code just in case anyone else finds it helpful.

Michael

[csharp]

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace ConsoleApplication1
{
class Program
{
[DllImport(@"CallbackTest.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void SetupFunction([MarshalAs(UnmanagedType.FunctionPtr)] MyDelegate del);
[DllImport(@"CallbackTest.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int RunFortranCallbackFunction();

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void MyDelegate(ref int val);

[STAThread]
static void Main()
{
// Set the delegate then pass to fortran
MyDelegate del = new MyDelegate(CSharpWriteToConsole);
SetupFunction(del);

// Call a fortran routine which will callback 'CSharpWriteToConsole '
RunFortranCallbackFunction();
}

internal static void CSharpWriteToConsole(ref int i)
{
Console.WriteLine(i);
}
}
}

[/csharp]

[fortran]

MODULE CallbackDll
IMPLICIT NONE

PROCEDURE(CSharpWriteToConsoleInterface), POINTER :: CSharpWriteToConsole

ABSTRACT INTERFACE
SUBROUTINE CSharpWriteToConsoleInterface(i)
INTEGER, INTENT(INOUT) :: i
END SUBROUTINE CSharpWriteToConsoleInterface
END INTERFACE

CONTAINS

!DEC$ ATTRIBUTES DLLEXPORT::SetupFunction
!DEC$ ATTRIBUTES ALIAS:'SetupFunction'::SetupFunction
SUBROUTINE SetupFunction(fPtr)
PROCEDURE(CSharpWriteToConsoleInterface) :: fPtr
INTEGER :: i

! Set Pointer
CSharpWriteToConsole => fPtr

END SUBROUTINE SetupFunction


!DEC$ ATTRIBUTES DLLEXPORT::RunFortranCallbackFunction
!DEC$ ATTRIBUTES ALIAS:'RunFortranCallbackFunction'::RunFortranCallbackFunction
FUNCTION RunFortranCallbackFunction() result(i)
INTEGER :: i, tmp

DO i = 1, 10
tmp = i
CALL CSharpWriteToConsole(tmp)
END DO

END FUNCTION RunFortranCallbackFunction

END MODULE CallbackDll

[/fortran]

0 Kudos
FortranFan
Honored Contributor III
868 Views

Glad to see it worked out.  Great catch on the PROCEDURE declaration in the SetupFunction - sorry for the mislead in my post, I was doing it from memory.

0 Kudos
Anthony_Richards
New Contributor I
867 Views

I cannot pretend to understand all the code, but it's pretty coolstuff.

Posters needing all types of C# - Fortran interplay will be beating a path to your door as a result IMO!

0 Kudos
onkelhotte
New Contributor II
867 Views

Thanks for the code. I use it now in my actual project!

Markus

0 Kudos
Reply