2016-12-05 113 views
2

含有指針我使用含有與以下簽名類型一個Fortran DLL一個Fortran類型工作(簡化):與來自託管代碼

TYPE MyType 
    INTEGER(4) :: ii 
    REAL(8) :: rr 
    INTEGER(4) :: n_a0 
    INTEGER(4) :: n_a1 
    INTEGER(4), POINTER :: a0(:) 
    REAL(8) , POINTER :: a1(:) 
    END TYPE 

顯然,這種類型的包含指向整數和雙精度。我通過以下方法順暢地從另一個Fortran代碼訪問此類型。

SUBROUTINE MySub(x) 
TYPE(MyType) :: x 

我的目標是通過C#代碼與MyTypeMySub工作。要做到這一點,我在我的C#代碼定義的結構如下:

struct MyType 
{ 
    public int ii; 
    public double rr; 

    public int n_a0; 
    public int n_a1; 

    public int[] a0; 
    public double[] a1; 
} 

,並用下面的方法訪問它:

[DllImport("my_test.dll", CallingConvention = CallingConvention.Cdecl)] 
    public static extern void MySub(ref MyType t); 

問題是當MySub訪問非陣列成員一切正常。但是當它試圖訪問數組元素時,我得到了AccessViolationException。我該怎麼做才能解決這個問題?

+0

我也嘗試將'a0'和'a1'的類型改爲'IntPtr'並使用'Marshal.AllocHGlobal'分配它們。但是在這種情況下我也得到了同樣的例外。 – melmi

回答

6

Fortran指針不是C指針。它們不能與C指針互操作。

雖然Fortran指向標量的指針往往只是地址下的地址,但數組指針並非如此。數組指針使用數組描述符,因爲數組可以不連續,指針還包含有關下限和上限的信息。

您應該創建另一個Fortran類型,該類型爲bind(C),其中包含C指針爲type(c_ptr)(在內部模塊iso_c_binding中定義)。

然後,你必須創建原始類型和新型之間的轉換,可以使用

c_interoperable_type%c_a0 = c_loc(old_type%a0(1)) 

我在這裏使用的第一要素,因爲陣列可能不是互操作設置C指針。但是,您必須確保自己的數組只是連續的。


如果你真的不能改變Fortran代碼你有麻煩了。當然可以找出數組地址在數組描述符中的位置,並直接從C中使用它。但我不能推薦它,它將是編譯器特定的,甚至可能是特定於版本的。