View previous topic :: View next topic |
Author |
Message |
kosh
Joined: 16 Dec 2009 Posts: 1
|
Posted: Wed Dec 16, 2009 10:13 pm Post subject: Parcing arrays from a Fortran subroutine to and from .NET |
|
|
My problem is probably trivial but yet I seem not to find a practical example anywhere in the forum as to how I proceed with the following.
I have an existing F90 code (compiled and running with Ftn95 in Visual Studio 2008) which handles complex matrix alegbra. Want to turn this into a Dll for use in a .Net graphical interface.
Problem: How do correctly exchange arrays between my Fortran subroutine
Subroutine complexMatrix (A,B)
real*8 A(1000)),B(1000)
..
..
End complexMatrix
and the .net environment where A is an array with input values for the Fortran subroutine and B contains output from the Fortran program for further processing in the .Net code.
Thanks in advance |
|
Back to top |
|
|
Andrew
Joined: 09 Sep 2004 Posts: 232 Location: Frankfurt, Germany
|
Posted: Tue Jan 05, 2010 4:25 pm Post subject: |
|
|
You could use something like:
Code: |
SUBROUTINE STUB(A,B)
ASSEMBLY_INTERFACE (NAME="CallStub")
REAL*8 A(:)
REAL*8 B(:)
CALL ROUTINE(A,B)
END
SUBROUTINE ROUTINE(A,B)
REAL*8 A(10),B(10)
DO I=1,10
B(I) = A(I)
END DO
END SUBROUTINE
|
And:
Code: |
double[] a = new double[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
double[] b = new double[] { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 };
FortranApplicationExtension.CallStub(a, b);
|
|
|
Back to top |
|
|
Andrew
Joined: 09 Sep 2004 Posts: 232 Location: Frankfurt, Germany
|
Posted: Wed Jan 06, 2010 11:05 am Post subject: |
|
|
Sorry, I also meant to say - an example can be found in the .NET example MatrixInvert in the FTN95 Examples folder (which is installed to My Documents). |
|
Back to top |
|
|
KennyT
Joined: 02 Aug 2005 Posts: 317
|
Posted: Fri Feb 05, 2010 11:58 am Post subject: Help! N00b question about calling .NET DLL |
|
|
Hi Andrew (or anyone else that can help!),
I've been given a .NET DLL with a simple function in it that I want to call from FTN95. Here's the function declaration:
Code: |
Public Class FortranDotNetTest
Public Function Calculate(ByVal FirstValue As Integer, ByVal SecondValue As Integer) As Integer
Return FirstValue * SecondValue
End Function
End Class
|
and here's the function call from within a .NET EXE:
Code: |
Private Sub btnCalculate_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCalculate.Click
Dim objCalculate As FortranDotNetTest.FortranDotNetTest
objCalculate = New FortranDotNetTest.FortranDotNetTest
txtResult.Text = objCalculate.Calculate(CInt(txtValueOne.Text), CInt(txtValueTwo.Text)).ToString
End Sub
|
Here's what I've tried (using /CLR /CLR_VER 2 in my compile line):
Code: |
!ftn95$free
!ftn95$LIBRARY 'FortranDotNetTestCOM.DLL'
!ftn95$ASSEMBLY_EXTERNAL ('FortranDotNetTest.FortranDotNetTest.Calculate') MYCALC
PROGRAM ATLAS_TEST
INTEGER I1, I2
I1 = 7
I2 = 4
I3 = ICalculate (I1, I2)
WRITE (*,*) "Result=",I3
END
FUNCTION ICALCULATE (I1, I2)
I1=7
I2=4
ICALCULATE = MYCALC (I1, I2)
END
|
But I get these errors at compile time:
Code: |
ERROR C:\Atlas\atlas_test.FOR 24: 1119: No .NET method matches this call
ERROR C:\Atlas\atlas_test.FOR 18: 126: Internal compiler error
|
Obviously, I'm missing a trick, but what is it?
Any advice welcomed.
TIA
K |
|
Back to top |
|
|
Andrew
Joined: 09 Sep 2004 Posts: 232 Location: Frankfurt, Germany
|
Posted: Fri Feb 05, 2010 12:10 pm Post subject: |
|
|
The .NET method is not static. You must call it therefore with an object reference. You need to create an instance of the object and pass it as the first argument to the method call. Something like:
Code: | assembly_external ('FortranDotNetTest.FortranDotNetTest.Calculate') MYCALC
object ("FortranDotNetTest.FortranDotNetTest") dotNetTest
dotNetTest = new@("FortranDotNetTest.FortranDotNetTest")
ICALCULATE = MYCALC(dotNetTest , I1, I2) |
|
|
Back to top |
|
|
KennyT
Joined: 02 Aug 2005 Posts: 317
|
Posted: Fri Feb 05, 2010 12:27 pm Post subject: |
|
|
THANK YOU!
It now compiles OK. All that is left is to link it against the supplied DLL!
My link command is:
Code: |
C:\Atlas>dbk_link2 atlas_test.dbk FortranDotNetTestCOM.dll
|
but I get:
Code: |
[DBK_LINK Ver. 2.0.0 Copyright(c) Silverfrost Ltd 2001-2009]
*** Reference to unknown type - FortranDotNetTest.FortranDotNetTest
|
K |
|
Back to top |
|
|
Andrew
Joined: 09 Sep 2004 Posts: 232 Location: Frankfurt, Germany
|
Posted: Fri Feb 05, 2010 12:31 pm Post subject: |
|
|
You need to use /R:assembly_name to specify DLLs for dbk_link to link to. |
|
Back to top |
|
|
KennyT
Joined: 02 Aug 2005 Posts: 317
|
Posted: Fri Feb 05, 2010 12:36 pm Post subject: |
|
|
Thanks for your patience with me on this:
I now get:
Code: |
C:\Atlas>dbk_link2 atlas_test.dbk /R:FortranDotNetTestCOM.dll
[DBK_LINK Ver. 2.0.0 Copyright(c) Silverfrost Ltd 2001-2009]
*** Could not reference assembly FortranDotNetTestCOM.dll
|
K
edit: OK, I was given two versions of the DLL. If I use the other (non COM) one, it links! However it doesn't run. I'll have to type up the error message, wait 5! |
|
Back to top |
|
|
KennyT
Joined: 02 Aug 2005 Posts: 317
|
Posted: Fri Feb 05, 2010 12:42 pm Post subject: |
|
|
OK, here's the runtime error:
Code: |
Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'FortranDotNetTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
File name: 'FortranDotNetTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'
at atlas_test.ICALCULATE(Int32* i1, Int32* i2)
at atlas_test.ATLAS_TEST()
|
K
edit: Aha! Can't change the original name of the DLL!!!! Think I'm on the path to righteousness, thank you for your help! |
|
Back to top |
|
|
KennyT
Joined: 02 Aug 2005 Posts: 317
|
Posted: Tue Feb 09, 2010 1:44 pm Post subject: |
|
|
Hi again (only me!)
I'm trying something else!
I'm trying to provide a "win32" DLL with functions that can be called from a .NET application. Is that possible, without resorting to C++ as an arbitrator?
If it is, what're the tricks?
TIA
K |
|
Back to top |
|
|
Andrew
Joined: 09 Sep 2004 Posts: 232 Location: Frankfurt, Germany
|
Posted: Tue Feb 09, 2010 1:54 pm Post subject: |
|
|
That should be possible. Just export your native routines as you would if calling from native C++ and then from .NET you then use a PInvoke to call the routines. |
|
Back to top |
|
|
KennyT
Joined: 02 Aug 2005 Posts: 317
|
Posted: Tue Feb 09, 2010 2:02 pm Post subject: |
|
|
OK, thanks, watch this space!
Can I test it with a FTN95 .NET main? Or, to put it another way, what's the FTN syntax for a "Pinvoke" - it doesn't seem to be mentioned in the help!
K |
|
Back to top |
|
|
Andrew
Joined: 09 Sep 2004 Posts: 232 Location: Frankfurt, Germany
|
Posted: Tue Feb 09, 2010 2:09 pm Post subject: |
|
|
There is no syntax for PInvoke from FTN95, it is not an FTN95 feature, but a .NET language feature that is in the Microsoft .NET languages.
You would have to call it using PInvoke from C# for example. You will have to write your own signature/import for the PInvoke, but there is plenty of information out there about how to do that. The following is an example of the definition of RegOpenKeyEx:
Code: | [DllImport("advapi32.dll", CharSet = CharSet.Auto)]
public static extern int RegOpenKeyEx(
UIntPtr hKey,
string subKey,
int ulOptions,
int samDesired,
out UIntPtr hkResult); |
You probably want to keep your types as simple as possible in the exposed routines. |
|
Back to top |
|
|
KennyT
Joined: 02 Aug 2005 Posts: 317
|
Posted: Tue Feb 09, 2010 2:30 pm Post subject: |
|
|
OK, but I can create a FTN95 .NET application, can't I? What I'm trying to do, for my sins, is to create a:
.NET main calling a W32 DLL so that I can then pass my W32 DLL to a third party .NET programmer with some instructions on how to call it. I only have experience of command-line driven FTN compile and link commands (probably because my mother was frightened by a Visual Studio programmer when I was in the womb, so I've never used it, VB.NET or C#!).
I'll ask the third-party programmer if he knows how to PInvoke something and hopefully, he'll say yes!
Thanks again for your help.
K |
|
Back to top |
|
|
Andrew
Joined: 09 Sep 2004 Posts: 232 Location: Frankfurt, Germany
|
Posted: Tue Feb 09, 2010 2:37 pm Post subject: |
|
|
You will not be able to call native code from an FTN95 .NET executable, there is no feature to allow for this. You (or the .NET programmer) will have to call it from Microsoft managed code via PInvoke if you want to do it via .NET. You can of course call your native Fortran routines from a native Fortran program too. |
|
Back to top |
|
|
|