从C#调用FORTRAN dll并将值分配给结构数组

时间:2011-06-03 19:29:54

标签: c# interop struct fortran

我可以将C#结构传递给FORTRAN就好了。我甚至可以在C#中将TYPE()结构的数组作为FORTRAN的数组传递。遇到麻烦的地方是我试图将值返回C#。这是一个例子:

fortran dll是:

MODULE TESTING

   TYPE VALUEREF
     INTEGER*4 :: A
   ENDTYPE VALUEREF

CONTAINS

   SUBROUTINE TEST_REF(T,N)
   !DEC$ ATTRIBUTES DLLEXPORT :: TEST_REF
   !DEC$ ATTRIBUTES ALIAS:'TEST_REF' :: TEST_REF
   !DEC$ ATTRIBUTES VALUE :: N
   IMPLICIT NONE
     INTEGER*4 :: A,I,N   
     TYPE(VALUEREF) :: T(N)      
     A = 100
     DO I=1,N
        T(I)%A = A + I
     END DO

   END SUBROUTINE
END MODULE

和期望结果的C#调用函数是:

[StructLayout(LayoutKind.Sequential)]
public struct ValueRef
{
    public int a;
}

[DllImport("mathlib.dll")]
static extern void TEST_REF(ValueRef[] t, int n);

void Main()
{
    ValueRef[] T = new ValueRef[4];
    for (int i = 0; i < T.Length; i++)
    {
        T[i].a = i;
    }
    Console.WriteLine("Initialize");
    for (int i = 0; i < T.Length; i++)
    {
        Console.WriteLine("  A={0}", T[i].a);
    }
    Console.WriteLine("Call Fortran");
    TEST_REF(T, T.Length);
    for (int i = 0; i < T.Length; i++)
    {
        Console.WriteLine("  A={0}", T[i].a);
    }
}

结果:

Initialize
  A=0
  A=1
  A=2
  A=3
Call Fortran
  A=0
  A=1
  A=2
  A=3

通过FORTRAN代码进行调试,我发现初始值从C#传递到FORTRAN就好了。使用新值覆盖值,并将控制权传递回C#,其中旧值仍包含在ValueRef个实例中。

为什么我能以类似的方式传递并返回floatint的数组,就好了。我可以使用ref关键字传递并返回奇异结构,但我可以通过返回struct的数组?

PS 的。我正在使用Compaq Visual Fortran 6.5&amp; .NET 3.5
PS2 。我对此有任何意见/想法表示感谢。我95%完成了我的项目,现在我遇到了这个问题。这个项目的重点是尽可能地使用结构来减少传递给函数的#of参数,并保留OOP设计的某些方面。

1 个答案:

答案 0 :(得分:4)

我过去使用指针而非数组完成此操作。我认为您的结构正在被复制用于P / Invoke调用:

[DllImport("mathlib.dll")]
static extern void TEST_REF(ValueRef* t, int n);

在调用方法之前,您需要固定数组。

fixed (ValueRef* pointer = t)
{
  TEST_REF(pointer, n);
}

修改 根据评论,解决方案是将外部声明为

[DllImport("mathlib.dll")]
static extern void TEST_REF([Out] ValueRef[] t, int n);

以下是关于数组封送的MSDN参考,以及它们默认[In]的方式。