Silverfrost Forums

Welcome to our forums

Parcing arrays from a Fortran subroutine to and from .NET

16 Dec 2009 9:13 #5565

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

5 Jan 2010 3:25 #5648

You could use something like:

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:

  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);
6 Jan 2010 10:05 #5651

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).

5 Feb 2010 10:58 #5905

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:

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:

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):

!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:

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

5 Feb 2010 11:10 #5907

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:

  assembly_external ('FortranDotNetTest.FortranDotNetTest.Calculate') MYCALC 
  object ('FortranDotNetTest.FortranDotNetTest') dotNetTest
  dotNetTest = new@('FortranDotNetTest.FortranDotNetTest') 
  ICALCULATE = MYCALC(dotNetTest , I1, I2) 
5 Feb 2010 11:27 #5908

THANK YOU!

It now compiles OK. All that is left is to link it against the supplied DLL!

My link command is:

C:\\Atlas>dbk_link2 atlas_test.dbk FortranDotNetTestCOM.dll

but I get:

[DBK_LINK Ver. 2.0.0 Copyright(c) Silverfrost Ltd 2001-2009]
*** Reference to unknown type - FortranDotNetTest.FortranDotNetTest

K

5 Feb 2010 11:31 #5909

You need to use /R:assembly_name to specify DLLs for dbk_link to link to.

5 Feb 2010 11:36 #5910

Thanks for your patience with me on this:

I now get:

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!

5 Feb 2010 11:42 #5911

OK, here's the runtime error:

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!

9 Feb 2010 12:44 #5938

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

9 Feb 2010 12:54 #5939

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.

9 Feb 2010 1:02 #5940

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

9 Feb 2010 1:09 #5942

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:

[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.

9 Feb 2010 1:30 #5943

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

9 Feb 2010 1:37 #5944

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.

9 Feb 2010 3:11 #5948

OK, he 'sprechen de VB', so hopefully he'll know what to do.

Tks

K

9 Feb 2010 3:26 #5950

I hate to correct on non-programming matters, but... 'Er spricht VB' or 'Er kann VB sprechen' - but then, I do now live in Germany... 😃

(And I hope that is actually correct!)

9 Feb 2010 5:23 #5953

Ver gudt!

:lol:

K

Please login to reply.