2011-06-03 89 views
4

我可以将C#结构传递给FORTRAN就好了。我甚至可以将C#结构的数组作为TYPE()的数组传递给FORTRAN。我遇到麻烦的地方是当我试图将值返回到C#时。下面是一个例子:从C#调用FORTRAN DLL并将值分配给结构数组

的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 & .NET 3.5
PS2。我很欣赏这方面的任何意见/想法。我完成了95%的项目,现在我遇到了这个问题。这个项目的重点是尽可能地使用结构来减少传递给函数的#参数,并保留OOP设计的某些方面。

+1

我想这取决于运行时如何编组你的值,这应该不是问题,它总是工作正常,我很惊讶地看到一个FORTRAN/C#混合。 – 2011-06-03 19:45:58

+0

注意反标格式不可用于标题,不幸的是 – AakashM 2011-06-03 21:12:59

+1

现实中的现代FORTRAN很容易和快速。我没有理由不仅为了保留遗留代码,而且在FORTRAN中开发新代码。当然对于GUI而言,我将它留给C#/ OpenTK。 – ja72 2011-06-04 03:30:07

回答

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]如何。

+0

我刚才建议......确保你用不安全的标志编译你的代码,并用unsafe关键字标记你的方法和范围,否则你会得到一堆编译错误。 – 2011-06-03 19:47:49

+0

当我传递一个单一的结构byref然后它不被复制,但是当我传递一个数组时,它被复制!? – ja72 2011-06-04 02:41:07

+1

您可以尝试的第二件事是使用P/Invoke签名中的[Out]属性。 – 2011-06-05 08:10:43