Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling a FORTRAN subroutine from C#

I want to import a FORTRAN DLL into visual C#. While I have done that with functions, the problem arises when I want to import a subroutine with multiple outputs. Here is a simple example:


FORTRAN DLL:

Subroutine MySub(a,b,x,y)

!DEC$ ATTRIBUTES DLLEXPORT, STDCALL, ALIAS:'MySub' :: MySub

Implicit None
Integer, INTENT(IN) :: a,b
Integer, INTENT(OUT) :: x,y

 y=a+b
 x=2*a+3*b
End Subroutine MySub

C# Console App:

using System;
using System.Runtime.InteropServices;

namespace AlReTest
{
    class Program
    {
    [DllImport(@"D:\...\AltRetTest.dll", CallingConvention=CallingConvention.StdCall)]
        public static extern int MySub(int a, int b, [Out] int x, [Out] int y);
        static void Main(string[] args)
        {
        int a = 4;
        int b = 3;
        int x = 0;
        int y = 0;
        MySub(a, b, x, y);

        Console.WriteLine(x);
        Console.WriteLine(y);
        Console.WriteLine(MySub(a, b, x, y));
        }
    }
}

Here are the answers that I get: x=0, y=0, MySub(a, b, x, y)=17

I'm a bit new in Visual C# programming, but I think above results mean that the two statements i.e. 'a+b' and '2*a+3*b' have been calculated but not assigned to x and y, and the latter (2*a+3*b) has been assigned to the function MySub itself! I have used OutAttributes in C#, also Intent[In], Intent[Out] in FORTRAN, but none have changed the results. I would appreciate any help or advice.

like image 270
user3275090 Avatar asked Oct 02 '22 00:10

user3275090


1 Answers

Like you I assumed that INTENT(OUT) would imply pass by reference. But it seems that is not the case. So you need to add the following to the FORTRAN to force pass by reference:

!DEC$ ATTRIBUTES REFERENCE :: x,y

The correct declaration of the function on the C# side is:

[DllImport(...)]
public static extern void MySub(int a, int b, out int x, out int y);

Call it like this:

MySub(a, b, out x, out y)

Note that you need to use the out keyword so that a pointer to the output variables is passed to the native code. You do need to use out or ref to make sure that the calling code sees the modified values.

Also note that the native function does not return a value. It's just a coincidence that the return value is passed through a register which by chance happened to contain the result of the last calculation that was performed.

like image 141
David Heffernan Avatar answered Oct 11 '22 13:10

David Heffernan