从C#调用FORTRAN子例程

use*_*090 5 c# pinvoke fortran dllimport

我想将FORTRAN DLL导入Visual C#.虽然我已经使用函数完成了这项工作,但是当我想导入具有多个输出的子例程时会出现问题.这是一个简单的例子:


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
Run Code Online (Sandbox Code Playgroud)

C#控制台应用:

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));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

以下是我得到的答案:x = 0,y = 0,MySub(a,b,x,y)= 17

我在Visual C#编程方面有点新,但我认为上面的结果意味着已经计算了两个语句,即'a + b'和'2*a + 3*b',但没有分配给x和y,并且后者(2*a + 3*b)已分配给MySub功能本身!我在C#中使用OutAttributes,还意图[IN],意图[OUT]在FORTRAN,但没有发生变化的结果.我将不胜感激任何帮助或建议.

Dav*_*nan 5

像你一样,我认为这INTENT(OUT)意味着通过引用传递。但事实似乎并非如此。因此,您需要将以下内容添加到 FORTRAN 中以强制按引用传递:

!DEC$ ATTRIBUTES REFERENCE :: x,y
Run Code Online (Sandbox Code Playgroud)

C# 端函数的正确声明是:

[DllImport(...)]
public static extern void MySub(int a, int b, out int x, out int y);
Run Code Online (Sandbox Code Playgroud)

像这样称呼它:

MySub(a, b, out x, out y)
Run Code Online (Sandbox Code Playgroud)

请注意,您需要使用out关键字,以便将指向输出变量的指针传递给本机代码。您确实需要使用outref来确保调用代码看到修改后的值。

另请注意,本机函数不返回值。返回值通过寄存器传递只是巧合,该寄存器碰巧包含上次执行的计算的结果。