1

我正在寻找将结构数组传递给非托管 C++ dll 的正确语法。

我的 dll 导入是这样调用的

    #define _DllImport [DllImport("Controller.dll", CallingConvention = CallingConvention::Cdecl)] static
_DllImport bool _Validation(/* array of struct somehow */);

在我的客户代码中,我有

List<MyStruct^> list;
MyObject::_Validation(/* list*/);

我知道 System::Runtime::InteropServices::Marshal 有很多有用的方法来做这样的事情,但我不确定该使用哪个。

4

2 回答 2

3

使用 StructLayout.Sequential 创建非托管结构的托管版本(确保以相同的顺序放置)。然后,您应该能够像将其传递给任何托管函数(例如,Validation(MyStruct[] pStructs) 一样传递它。

例如,假设我们的原生函数有这个原型:

extern "C" {

STRUCTINTEROPTEST_API int fnStructInteropTest(MYSTRUCT *pStructs, int nItems);

}

而原生的 MYSTRUCT 定义如下:

struct MYSTRUCT
{
    int a;
    int b;
    char c;
};

然后在 C# 中,定义结构的托管版本,如下所示:

[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public struct MYSTRUCT
{
    public int a;
    public int b;
    public byte c;
}

托管原型如下:

    [System.Runtime.InteropServices.DllImportAttribute("StructInteropTest.dll", EntryPoint = "fnStructInteropTest")]
    public static extern int fnStructInteropTest(MYSTRUCT[] pStructs, int nItems);

然后,您可以调用该函数,并传递一个 MYSTRUCT 结构数组,如下所示:

    static void Main(string[] args)
    {
        MYSTRUCT[] structs = new MYSTRUCT[5];

        for (int i = 0; i < structs.Length; i++)
        {
            structs[i].a = i;
            structs[i].b = i + structs.Length;
            structs[i].c = (byte)(60 + i);
        }

        NativeMethods.fnStructInteropTest(structs, structs.Length);

        Console.ReadLine();
    }
于 2009-04-09T17:14:48.950 回答
1

您可以使用Marshall.StructureToPtr来获取一个 IntPtr,该 IntPtr 可以传递到本机 MyStruct* 数组中。

但是,我不确定如何直接从列表中执行此操作。我相信您需要将其转换为数组并使用 pin_ptr (以防止 GC 移动您的内存),然后再将其传递给本机代码。

于 2009-04-09T16:49:29.997 回答