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

Calling a Fortran Dll with c# - Mixing Fortran with c#

gilac
Beginner
781 Views
I have one bigproblem... so, please, anyone can help me?
I want to call a Fortran Dll with a C# program. And I have problems with the calling sintax and with the compatibility of the arguments.
My C# program needs an array return from a Fortran Dll. The Fortran is like this:
SUBROUTINE FTOCCONVERT(VIN,VOUT)
IMPLICIT NONE
! Expose subroutine FTOCCONVERT to users of this DLL
!Dec$ ATTRIBUTES DLLEXPORT, STDCALL :: FTOCCONVERT
!Dec$ ATTRIBUTES ALIAS:'FTOCCONVERT' :: FTOCCONVERT
!!DEC$ ATTRIBUTES REFERENCE::VOUT
REAL(8), INTENT(IN)::VIN(4)
REAL(8), INTENT(OUT)::VOUT(4)
write(*,*)'subroutine VIN=',VIN(1),VIN(2)
write(*,*)'subroutine VOUT=',VOUT(1)
VOUT(1) = ((VIN(1)-32.0)*5.0/9.0)
VOUT(2) = 999.0
write(*,*)'subroutine Vin=',VIN(1)
write(*,*)'subroutine Vout=',VOUT(1)
RETURN
END
And I use PInvoke to call it...
The C# console code is like this:
using System;
using System.Runtime.InteropServices; //for PInvoke
namespace Testconversion
{
class Class1
{
[DllImport("FTOCCONVERT.dll")]
public static extern double FTOCCONVERT(double VIN);

[STAThread]
static void Main(string[] args)
{
System.Console.Write("Enter a value and enter: ");
string str = System.Console.ReadLine();
double[] VIN = new double[4];
double[] VOUT = new double[4];
VIN[1]=Convert.ToDouble(str);
VIN[2]= 200.0;
VOUT[1]= FTOCCONVERT(VIN[1]);
System.Console.WriteLine(" Vin= {0}; cent= {1};",VIN[1],cent);
System.Console.WriteLine("The result is: {0} ",VOUT[1]);
}
}
}
When I don't use arrays, the info enters the fortran Dll but the result is NaN (not an number). But with arrays I got a NullReferenceException.
I already tested the fortran Dll with a fortran code and with a VB.NET with sucess!

What is wrong with the Fortran or C# code?
What is the equivalence (compatibility)between c# and Fortran? double is equivalent to Real(8)? and the others type of variables?
And if the arguments changed? per example, without arrays?
Thank everybody...I really hope to have some reply!
Regards,
gilac
0 Kudos
3 Replies
sabalan
New Contributor I
781 Views

First of all you must know that the indexes of arrays in C# begin with 0 while they begin with 1 in Fortran. Therefore you have to initialize your VIN with VIN[0] and VIN[1], and get VOUT with index [0] on C# side.

I changed the following lines in C# as you see them here:

public static extern double FTOCCONVERT(ref double VIN, ref double VOUT);

VIN[0]=Convert.ToDouble(str);
VIN[1]= 200.0;

VOUT[0]=FTOCCONVERT(ref VIN[0], ref VOUT[0]);


And on Fortran side added:

!DEC$ ATTRIBUTES REFERENCE::VIN
!DEC$ ATTRIBUTES REFERENCE::VOUT


And it worked for me. There are some problems with your last 2 lines in C# but I don't know what,becausemy knowledge in C# is almost 0! I commented out those lines and got the answer in the console anyway.

Hope this helps,

Sabalan.


0 Kudos
gilac
Beginner
781 Views
Thank very muchSabalan for your help...
Now it woks but....the results obtained (seen with the debug) are:
VOUT[0]=NaN
VOUT[1]=999.0
I think that there's an error in the conversion of the argument VOUT(1) in the Fortran subroutine to the VOUT[0] in the c# program.
There's the Fortran Dll:

SUBROUTINE

FTOCCONVERT(VIN,VOUT)

IMPLICIT NONE

!Dec$ ATTRIBUTES DLLEXPORT, STDCALL :: FTOCCONVERT

!Dec$ ATTRIBUTES ALIAS:'FTOCCONVERT' :: FTOCCONVERT

!DEC$ ATTRIBUTES REFERENCE::VIN

!DEC$ ATTRIBUTES REFERENCE::VOUT

REAL(8), INTENT(IN)::VIN(4)

REAL(8), INTENT(OUT)::VOUT(4)

VOUT(1) = ((VIN(1)-32.0)*5.0/9.0)

VOUT(2) = 999.0

RETURN

END

and here is the c# program:

using System;

using System.Runtime.InteropServices; //for PInvoke

namespace Testconversion

{

class Class1

{

[DllImport("FTOCCONVERT.dll")]

public static extern double FTOCCONVERT(ref double VIN, ref double VOUT);

[STAThread]

static void Main(string[] args)

{

System.Console.Write("Enter a value and enter:");

string str = System.Console.ReadLine();

double[] VIN = new double[4];

double[] VOUT = new double[4];

VIN[0]=Convert.ToD ouble(str);

VIN[1]= 200.0;

VOUT[0]= FTOCCONVERT(ref VIN[0],ref VOUT[0]);

System.Console.WriteLine("The result Vout is: {0} ",VOUT[0]);

}

}

}

And the results:
In the end of theFortran Subrotine (taken from the debug window):
VIN(1)300.000000000000REAL(8)
VIN(2)200.000000000000REAL(8)
VIN(3)0.000000000000000E+000REAL(8)
VIN(4)0.000000000000000E+000REAL(8)
VOUT(1)148.888888888889REAL(8)
VOUT(2)999.000000000000REAL(8)
VOUT(3)0.000000000000000E+000REAL(8)
VOUT(4)0.000000000000000E+000REAL(8)
After the return to the C# program:
-VIN{Length=4}double[]
[0]300.0double
[1]200.0double
[2]0.0double
[3]0.0double
-VOUT{Length=4}double[]
[0]NaNdouble
[1]999.0double
[2]0.0double
[3]0.0double

I hope you can help me...

regards,

gilac


0 Kudos
sabalan
New Contributor I
781 Views

As I said my knowledge in C# is nothing to count with. But What I can see is that the problem shows to be the way you declare and call the DLL. I changed the DLL declaration to "public static extern bool", declared a new variable "bool Ret;" and changed the call to:

Ret = FTOCCONVERT(

ref VIN[0], ref VOUT[0]);

Now you get VOUT as it should be and Ret = False. But I have no idea if one has to do it this way or not! I think you should find how to declare and call DLLs if you search this forum for C#, or search C# forums somewhere else.
Sabalan.
0 Kudos
Reply