从C#调用FORTRAN dll并为结构数组赋值

本文关键字:结构 数组 赋值 dll 调用 FORTRAN | 更新日期: 2023-09-27 17:58:17

我可以很好地将C#结构传递到FORTRAN中。我甚至可以将C#结构的数组作为FORTRANTYPE()的数组传递。当我试图将值返回到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

并且期望结果的CCD_ 7调用函数是:

[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&NET 3.5
PS2。我很感激对此发表任何意见/想法。我已经完成了95%的项目,现在我遇到了这个问题。这个项目的全部目的是尽可能多地使用结构,以减少传递给函数的参数数量,并保留OOP设计的某些方面。

从C#调用FORTRAN dll并为结构数组赋值

我过去使用指针而不是数组来完成此操作。我认为您的结构正在被复制用于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]