代码之家  ›  专栏  ›  技术社区  ›  Eric

如何将C++/CLI数组配置为非托管C++

  •  1
  • Eric  · 技术社区  · 15 年前

    我正在寻找正确的语法来将结构数组传递给非托管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有很多这样有用的方法,但我不确定要使用哪种方法。

    2 回复  |  直到 15 年前
        1
  •  3
  •   Shea    15 年前

    使用structlayout.sequential创建非托管结构的托管版本(确保按相同顺序放置)。然后您应该能够像传递给任何托管函数一样传递它(例如,验证(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();
        }
    
        2
  •  1
  •   Reed Copsey    15 年前

    你可以使用 Marshall.StructureToPtr 以获取可传递到本机mystrut*数组的intptr。

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