使用C#中的Marshal.StructureToPtr将结构传递给C ++ API

我在我的代码中使用C ++编写的API(用C#编写)。 API需要一个参数作为指向结构的指针。 结构由“Int”和Char Arrays组成:例如

unsafe public struct ToBePassed { Int32 Num1; Int32 Num2; Char[] Data; // or fixed Char Data[255]; } 

我不能直接将结构指针传递给API,因为在这种情况下,我收到错误,因为“指针不能引用Marshaled结构”。 代码编译成功但是当我执行(调试)代码时会出现此错误。

现在我有两个选择:第一: – 通过Ref传递结构:我想问一下当我通过ref传递结构时,需要结构指针的API是否可以接收地址。 请注意,API将在“Char [] Data”中返回Data。

第二: – 使用Marshal.StructureToPtr:这会将结构指针转换为IntPtr。 怀疑是相同的,API会正确接收吗?

谢谢你的时间!

此致,Swanand

如果它只需要指针,您可以分配一些非托管内存,将结构编组到内存中,并将该指针传递给您的函数。 然后你可以编组回到结构(如果你愿意)并释放内存。 在编组任何内容之前,您需要正确定义结构。 像这样的东西:

 [StructLayout( LayoutKind.Sequential, //must specify a layout CharSet = CharSet.Ansi)] //if you intend to use char public struct ToBePassed { public Int32 Num1; public Int32 Num2; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 255)] public Char[] Data; //specify the size using MarshalAs } [DllImport("...")] public static extern void APICall(IntPtr argPtr); public static void CallFunction(ToBePassed managedObj) { IntPtr unmanagedAddr = Marshal.AllocHGlobal(Marshal.SizeOf(managedObj)); Marshal.StructureToPtr(managedObj, unmanagedAddr, true); APICall(unmanagedAddr); Marshal.PtrToStructure(unmanagedAddr, managedObj); Marshal.FreeHGlobal(unmanagedAddr); unmanagedAddr = IntPtr.Zero; } 

[编辑]
要模拟可变长度数组,请在结构中分配非托管内存并像往常一样进行初始化。

 [StructLayout(LayoutKind.Sequential)] public struct SomeStruct { public Int32 X; public Int32 Y; } [StructLayout(LayoutKind.Sequential)] public struct VLA { public Int32 intArrayLength; public Int32 SomeStructArrayLength; public IntPtr intArray; public IntPtr SomeStructArray; } public static VLA CreateVLA(int[] intArray, SomeStruct[] SomeStructArray) { var vla = new VLA() { intArrayLength = intArray.Length, SomeStructArrayLength = SomeStructArray.Length, intArray = Marshal.AllocHGlobal(intArray.Length * Marshal.SizeOf(typeof(int))), SomeStructArray = Marshal.AllocHGlobal(SomeStructArray.Length * Marshal.SizeOf(typeof(SomeStruct))), }; Marshal.Copy(intArray, 0, vla.intArray, intArray.Length); //there's no overload to copy arbitrary arrays, do it manually for (int i = 0; i < SomeStructArray.Length; i++) { Marshal.StructureToPtr( SomeStructArray[i], vla.SomeStructArray + i * Marshal.SizeOf(typeof(SomeStruct)), true); } return vla; }