C# 从C调用FORTRAN子例程#

C# 从C调用FORTRAN子例程#,c#,fortran,pinvoke,dllimport,C#,Fortran,Pinvoke,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

我想将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
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));
        }
    }
}

C#控制台应用程序:

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


我对VisualC编程有点陌生,但我认为上面的结果意味着两条语句,即“a+b”和“2*a+3*b”已经计算过,但没有分配给x和y,后者(2*a+3*b)已经分配给函数MySub本身!我在C#中使用了OutAttributes,在FORTRAN中也使用了Intent[in],Intent[Out],但没有一个更改结果。我将非常感谢任何帮助或建议。

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

!DEC$ ATTRIBUTES REFERENCE :: x,y
C端函数的正确声明是:

可以这样称呼:

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


还要注意,本机函数不返回值。只是巧合,返回值通过了一个寄存器,该寄存器碰巧包含了上次执行的计算结果。

我按照您的建议@David,仍然得到相同的答案。如果您告诉我们您在Fortran中使用的编译器,可能会有所帮助。首先,我使用了out修饰符,结果没有变化,然后我使用了ref和out,正如您所提到的,结果变为0、0和一个八位数,如14394268!!!!有趣的是,每次我运行代码时,这个数字都会改变。我使用Compaq Visual Fortran解决了这个问题,我添加了“!DEC$ATTRIBUTES REFERENCE::X,Y'引用到我的FORTRAN代码中,并在c#代码中使用了out修饰符,得到了正确的结果。谢谢@davideines,我从你的第一句评论中意识到,out的意图并不意味着我们都预期的参考。因此需要编译器的详细信息。但从那以后我就离开了,没有机会深入挖掘。干得好,把我打败了。我会在适当的时候更新答案。您使用的是哪种Fortran编译器?@ClickRick阅读下面答案上的评论,我使用的是Compaq Visual Fortran 6.6。通过在我的FORTRAN DLL中添加一个引用属性解决了这个问题。正如我所看到的(在我询问之后您回答了这一点),但您和David显然已经讨论过了,所以没有进一步评论。