Silverfrost Forums

Welcome to our forums

Passing .NET array from FORTRAN to C#

30 Jun 2008 7:24 #3435

I am trying, so far without success, to pass an entire array from FORTRAN to C#.NEt. I understand that a .NET array must be created and instantiated in FORTRAN and that I must assign values to each of its values from a FORTRAN array by adjusting for i = 0 versus i = 1 initial index. The question is how to pass this array to C#. I tried

ASSEMBLY_EXTERNAL('System.Array.Copy') :: ArrayCopy

My idea was to copy the C# array created in the FORTRAN subroutine to a specific C# array passed as an argument to the fortran subroutine. Is this the best way of doing this?

Secondly, it looks as if using the instance method Array.SetValue I can assign to each element of an array but it would be better if I could use the static method Array.Copy or else another, more intelligent way of doing the same thing. I would appreciate any guidance.

1 Jul 2008 11:23 #3438

It is not clear to me what you are aiming to do.

Have you read the FTN95 help topic under .NET platform->.NET programming->.NET arrays?

1 Jul 2008 4:03 #3439

Yes, I did read it, but how to do what I am asking was not clear to me from the documentation. Basically, I need to get a Fortran array calculated in the Fortran subroutine and pass that to the .NET code that called the Fortran subroutine.

The documentation or perhaps one of the examples does talk clearly about the reverse operation, which is how to pass an array to a Fortran subroutine and how to convert that to a Fortran array. If there is something as clear on the reverse operation, please point me to it.

Thanks.

2 Jul 2008 6:07 #3440

If you are passing a Fortran array as an argument then you may get some ideas by looking at the ildasm of the compiled code. This will show you the number and type of the actual arguments that are being passed.

The array will appear as a pointer to a contiguous block of column-ordered data. In the C# code you may be able to use 'unsafe' pointers to extract the data into a more usable form.

However, there is probably a simpler way to do the transfer.

3 Jul 2008 7:47 #3441

An example of passing .NET arrays from Fortran can be found here:

https://forums.silverfrost.com/Forum/Topic/828

This is a specific example to demonstrate what to do with a byte array, but its easy to adapt to what you need.

The code example from the above link is below:

Fortran

INTEGER F_ARRAY(256)
OBJECT('ClassLibrary3.Class1') :: OBJ
ASSEMBLY_EXTERNAL(name='ClassLibrary3.Class1.TestRoutine') :: TESTROUTINE
OBJECT('System.Int32[]') C_ARRAY

OBJ = new@('ClassLibrary3.Class1')

C_ARRAY=NEW@('System.Int32[]',256)

! make sure the indexing is correct
DO I=0,255
    F_ARRAY(I + 1) = I
    C_ARRAY(I) = F_ARRAY(I + 1)
END DO

CALL TESTROUTINE(OBJ, C_ARRAY)
END PROGRAM 

C#

public void TestRoutine(int[] arr)
{
     byte[] ba = new byte[arr.Length];
     for (int i = 0; i < arr.Length; i++)
     {
         ba[i] = Convert.ToByte(arr[i]);
     }
}

If you need to actually return a .NET array then you can declare a function that returns this, or you could pass a .NET array in as an INTENT(INOUT) and declare it appropriately in the C#.

Passing arrays like this around, so long as they are .NET arrays should be no issue. As you say, you just need to make sure the indexing is OK and as you can see in the example, you can create and assign as shown.

16 Jul 2008 8:08 #3469

I will experiment with it. If you don't mind, I will follow up if I have some additional questions.

18 Jul 2008 11:14 #3476

What does this line do?

OBJECT('ClassLibrary3.Class1') :: OBJ

I have the Fortran code as a reference in the C# Windows Form Application, so I don't have a class library.

With respect to passing the array as INTENT(INOUT), is there sample code somewhere in the forum or can youo provide an example?

Thanks.

19 Jul 2008 2:03 #3486

It's not all that difficult once you get used to it. To copy an array from c# to a Fortran subroutine and back again, assuming the routine has the array as it's only parameter:

SUBROUTINE MESS_WITH_IT(c_array)
  1. Declare the c# array in FTN instantate it:

    OBJECT ('System.Int32[]') c_array c_array=NEW@('System.Int32[]',MAXSIZE)

  2. Copy it to a FTN array:

    DO I=1,MAXSIZE F_ARRAY(I)=c_array(I-1) END DO

  3. Do what you have to do with the array, then copy it back to the c# array and return:

    DO I=1,MAXSIZE c_array(I-1)=F_ARRAY(I) END DO

    RETURN

I think this will work with any numeric array EXCEPT for a BYTE array. Unsigned bytes must be first converted to at least Int16 to pass. In FTN, the array can be copied to a byte array, if needed.

19 Jul 2008 8:56 #3492

My call to the the fortran dll has several arguments, including several arrays. It is not clear to me how C# gets the array from Fortran. Doing just the return that you suggested did not appear to do the job.

19 Jul 2008 11:38 #3493

I pass the the C# array as reference, then declare it within the Fortran subroutine as INTENT(INOUT), then change it. This is probably what Andrew had suggested originally.

Thank you all for the help.

Please login to reply.