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

c# Csharp Delegate callback

sscoleman
Beginner
410 Views
I am getting weird results. The loop never finishes.
If I take the print out it return after 2 loops without the error.
Anyone have an idea why this is happening?

Here is my code.

C#
----------------------------
// C# calling Fortran example
// Part of the Intel Visual Fortran sample programs
using System;
using System.Runtime.InteropServices;

namespace ConsoleApplication4
{
///
/// Summary description for Class1.
///

class Class1
{
delegate int DoSomething(int a);
///
/// The main entry point for the application.
///

[DllImport(@"visualfortranDll1.dll")]
public static extern void visualfortranDll1(
[MarshalAs(UnmanagedType.I4)]int len,
[MarshalAs(UnmanagedType.FunctionPtr)] System.Delegate delg,
[MarshalAs(UnmanagedType.I4)] out int num);
[STAThread]
static void Main(string[] args)
{
DoSomething ds = new DoSomething(updateText);
int len = 1000;
int returnval = 0;
visualfortranDll1(len, ds, out returnval);
Console.WriteLine(returnval);
Console.ReadLine();
}
private static int updateText(int x)
{
Console.WriteLine("delegate value=" + x);
return 400;
}
}
}

FORTRAN
----------------------------

C! visualfortranDll1.f90
C!
C! FUNCTIONS/SUBROUTINES exported from visualfortranDll1.dll:
C! visualfortranDll1 - subroutine
C!
subroutine visualfortranDll1(r1, f, num)

C ! Expose subroutine visualfortranDll1 to users of this DLL
C !
!DEC$ ATTRIBUTES DLLEXPORT::visualfortranDll1
!DEC$ ATTRIBUTES ALIAS:'visualfortranDll1'::visualfortranDll1
!DEC$ ATTRIBUTES VALUE :: r1

C ! Variables
integer, INTENT(IN) :: r1
integer, INTENT(OUT) :: num
integer :: f

integer II
integer Y

C ! Body of visualfortranDll1

do 10 II = 1, r1
y = f(II)
num = y
print * , num
10 continue
end subroutine visualfortranDll1


Command Window Results
----------------------------

delegate value=1242544
400
delegate value=1242544
400
delegate value=1242544
0
delegate value=1242544
forrtl: severe (8): internal consistency check failure, file src/libfor/for_desc
_item.c, line 582
Image PC Routine Line Source
libifcoremd.dll 02EBEB4A Unknown Unknown Unknown
libifcoremd.dll 02EBBDC8 Unknown Unknown Unknown
libifcoremd.dll 02E8357A Unknown Unknown Unknown
libifcoremd.dll 02E9A6E9 Unknown Unknown Unknown
libifcoremd.dll 02E8D409 Unknown Unknown Unknown
libifcoremd.dll 02E8CF22 Unknown Unknown Unknown
visualfortranDll1 10001060 visualfortranDll1 27 visualfortranDll1.f
00A0A0D6 Unknown Unknown Unknown
mscorwks.dll 791D94BC Unknown Unknown Unknown
mscorwks.dll 791ED194 Unknown Unknown Unknown
mscorwks.dll 791ED54B Unknown Unknown Unknown
mscorwks.dll 791ED5B9 Unknown Unknown Unknown
mscorwks.dll 7921D82B Unknown Unknown Unknown
mscorwks.dll 7921DA72 Unknown Unknown Unknown
mscorwks.dll 7921D6E5 Unknown Unknown Unknown
mscorwks.dll 7921D630 Unknown Unknown Unknown
mscorwks.dll 791C71EF Unknown Unknown Unknown
mscorwks.dll 791C70AE Unknown Unknown Unknown
KERNEL32.dll 7C816D4F Unknown Unknown Unknown


0 Kudos
2 Replies
Steven_L_Intel1
Employee
410 Views
Try adding the STDCALL attribute to the Fortran routine and see what happens. I'm not sure if this is required - the MS documentation is unclear where I've looked - and I am not certain I have this right in the C# sample I provided. You'll also need to specify STDCALL for F, I think - an explicit interface would be good here.

I have no idea if one can actually do what you want here - I don't know if C# provides the ability for unmanaged code to call back into it.
0 Kudos
sscoleman
Beginner
410 Views

I uploaded a working project. Hope this helps someone else. There is hardly any documentation for C#. I would like to point out anything you can do in VB you can do betterin c#! It's all .NET!smiley [:-)]

Code is below


C#

using System;

using System.Runtime.InteropServices;

//It only makes sense that if VB can do this so can C#.

namespace ConsoleApplication

{

class Class1

{

private delegate int DoSomething(ref int a);

private DoSomething ds;

[DllImport(@"visualfortranDll1.dll")]

public static extern int VFDLL([MarshalAs(UnmanagedType.FunctionPtr)] System.Delegate delg);

[STAThread]

static void Main()

{ Class1 DoIt = new Class1();

DoIt.startDo();

}

private void startDo()

{

ds = new DoSomething(updateText);

Console.WriteLine("My Fortran DLL returned " + VFDLL(ds));

Console.ReadLine();

}

private int updateText(ref int x)

{

Console.WriteLine("I got the value " + x +

" from FORTRAN");

return 400;

}

}

}

FORTRAN


integer function VFDLL(f)

!Expose subroutine VFDLL to users of this DLL

!DEC$ ATTRIBUTES DLLEXPORT::VFDLL

!DEC$ ATTRIBUTES ALIAS:'VFDLL'::VFDLL

! Variables

integer :: f

integer Y

!Logic

do Y=1, 25

call CallDelegate(f,Y)

end do

VFDLL = Y

end function VFDLL

subroutine CallDelegate(f, Y)

integer :: f

integer Y

integer num

write (*,*) 'Sending delegate ' , Y

num = f(Y)

write (*,*) 'Return value from C# delegate is' , num

end subroutine CallDelegate


If anyone finds this helpfull leave a post. It's nice to know when your helpful.Open-mouthed smiley [:-D]

Also really good to know, FORTRAN uses by default by REF so if you are calling an API you can actually check the OUT values(from the caller(C#))at any time and see the changes. You do not have to wait until the API returns. Opens a whole new area for property callbacks in the setters. Cool huh!

0 Kudos
Reply