用C#调用FORTRAN子程序

5

我想将一个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

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));
        }
    }
}

以下是我得到的答案: 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,在FORTRAN中使用了Intent[In]、Intent[Out],但都没有改变结果。我会感激任何帮助或建议。

你使用的是哪个Fortran编译器? - ClickRick
@ClickRick 请查看下面答案的评论,我使用的是 Compaq Visual Fortran 6.6。通过在我的 FORTRAN DLL 中添加引用属性,问题得到了解决。 - user3275090
我看到了(你在我提问之后回答了那一部分),但是你和David显然已经把它搞定了,所以我没有再发表评论。 - ClickRick
1个回答

5

和你一样,我也认为INTENT(OUT)应该意味着按引用传递。但事实并非如此。因此,您需要将以下内容添加到FORTRAN代码中,以强制按引用传递:

!DEC$ ATTRIBUTES REFERENCE :: x,y

在C#端,函数的正确声明方式是:

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

这样调用:

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

请注意,您需要使用out关键字,以便将输出变量的指针传递给本地代码。您确实需要使用outref来确保调用代码看到修改后的值。
还要注意,本地函数不返回值。这只是一个巧合,返回值通过寄存器传递,恰好包含了上一次执行的计算结果。

我按照你建议的做了,@David,但仍然得到相同的答案。 - user3275090
告诉我们你在用哪个Fortran编译器可能会有所帮助。 - David Heffernan
首先我使用了out修饰符,结果没有变化,然后我按照你的建议使用了ref和out,结果变成了0、0和一个八位数,比如14394268!!!有趣的是,这个数字每次运行代码时都会改变。我使用Compaq Visual FORTRAN。 - user3275090
问题解决了,我在我的FORTRAN代码中添加了'!DEC$ ATTRIBUTES REFERENCE :: X,Y',并在C#代码中使用了out修饰符,我得到了正确的结果。谢谢@David。 - user3275090
是的,我从你的第一条评论中意识到out的意图并不像我们预想的那样涉及到引用。因此请求编译器细节。但那之后我一直在外面,没有机会深入挖掘。很高兴你比我先发现了问题。我会适时更新答案。 - David Heffernan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接