簡體   English   中英

通過結構指針將結構數組從 C# 傳遞給 C

[英]Pass array of struct to C from C# via struct pointer

我想將一個結構數組從 C# 傳遞給 C dll。

C中的結構定義:

typedef struct{
    BYTE name[32];
    DWORD age;
}DATA;

我將結構編組如下:

[StructLayout(LayoutKind.Sequential)]
public struct DATA
{
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
    public byte[] name;
    public int age;
}

我要傳遞的 C 函數定義:

void test_data(DATA * pStruct, DWORD length){
    _tprintf("test start\n");
    
    if (!pData)
    {
        _tprintf("pData is NULL\n");
    }
    unsigned int i,j;
    
    for(i = 0; i < length; i++){
        _tprintf("name: ");
        for(j = 0; j < 32; j++){
            _tprintf("%x ",pData[i].name[j]);
        }
        _tprintf("\n");
        _tprintf("age: %d",pData[i].age);
        _tprintf("\n");
    }

    _tprintf("test finish\n");
}

C#中的函數簽名:

[DllImport("a.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void test_data(ref DATA pData, int length);

C#中的設置:

int length = 10;
DATA[] arr = new DATA[length];
for(int i = 0; i < length; i++){
  arr[i].name = new byte[32];
  arr[i].age = 10;
}

test_data(ref arr[0], length);

但我得到了這些輸出:

test start
name: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
age: 10
name: 7c 67 9a 2 a 0 0 0 1 0 0 0 2 0 0 0 eb 9 77 67 a4 eb 8f 0 0 0 0 0 2 0 0 0
age: 43673448
test finish

第一個是正確的,但第二個似乎很奇怪,我認為我通過引用或進行設置的方式有問題。

我的靈感來自 SCardTransmit 函數中pinvoke 網絡,它使用ref rapdu[0]將 C# 中的字節數組傳遞給 C 中的byte *

如何正確地做到這一點?

這不是您將結構數組從托管代碼編組為本機代碼的方式。

在您的 P/Invoke 聲明中:

[DllImport("a.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void test_data(ref DATA pData, int length);

ref DATA pData編組到指向單個DATA對象的指針。 無法保證陣列的其余部分將與它一起發送。 如果您的結構是blittable ,它可能會起作用,因為然后編組它只涉及固定數組,然后將其地址按原樣傳遞給 C 函數。 但是,唉,該結構包含一個數組,它是一個引用類型。 當您將它傳遞給 C 函數時,封送拆收器必須進行復制以獲取具有正確布局的結構。 因此,當您通過ref arr[0]時,您只會發送一份副本,然后您的 C 代碼會直接離開緩沖區的末尾,並且您會遇到未定義的行為。 而且,在更哲學的層面上, pData應該是一個數組也不太清楚。

因此,要發送整個批次,只需將您的參數聲明為數組, 如文檔中所述,其余的將由編組器完成:

[DllImport("a.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void test_data(DATA[] pData, int length);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM