- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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:
- C# passes Fortran the memory address of the C# routine to call in the exe when progress has changed (as a delegate?)
- Fortran dll updates a module procedure pointer to point to this C# routine so that it can call it later on
- C# starts the main fortran "DoWork" function
- 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
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Michael,
See if the attached is of any help,
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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]
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for the code. I use it now in my actual project!
Markus

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page