将浮点数组编组到c#

我正在尝试编组一个包含从C ++ DLL到C#的float-Array的结构。

我从以下代码创建了C ++ DLL:

//MarshalTest.h namespace mTest{ typedef struct { float data[3]; int otherStuff; } dataStruct; extern "C" __declspec(dllexport) dataStruct getData(); } //MarshalTest.cpp #include "MarshallTest.h" using namespace std; namespace mTest{ dataStruct getData(){ dataStruct d = {{ 16, 2, 77 }, 5}; return d; } } 

我使用以下代码使得C#中的getData-Function可用:

 public unsafe struct dataStruct{ public fixed byte data[3]; public int otherStuff; public unsafe float[] Data{ get{ fixed (byte* ptr = data){ IntPtr ptr2 = (IntPtr)ptr; float[] array = new float[3]; Marshal.Copy(ptr2, array, 0, 3); return array; } } set{ fixed (byte* ptr = data){ //not needed } } } } [DllImport("MarshallTest", CallingConvention = CallingConvention.Cdecl)] private static extern dataStruct getData (); 

在C#中打印数据[]时,我得到以下输出:1.175494E-38 1.610935E-32 8.255635E-20

我究竟做错了什么?

您必须使用正确的类型:

 public unsafe struct dataStruct2 { public fixed float data[3]; public int otherStuff; public unsafe float[] Data { get { fixed (float* ptr = data) { float[] array = new float[3]; Marshal.Copy((IntPtr)ptr, array, 0, 3); return array; } } } } 

请注意,对于小型数组,您甚至可以使用:

 public struct dataStruct { public float data1; public float data2; public float data3; public int otherStuff; public float[] Data { get { return new[] { data1, data2, data3 }; } } } 

不使用不安全的代码。

我不确定你为什么要做所有不安全的东西和指针操作。 如果你正确定义你的结构,它很简单:

 [StructLayout(LayoutKind.Sequential)] public struct dataStruct { [MarshalAs(UnmanagedType.LPArray, SizeConst = 3)] public float[] data; public int otherStuff; } 

您只需要向interop marshalling指示有关您的类型的一些其他信息,然后您可以获得非托管数据而不使用不安全的构造和指针。 在C#中使用指针的原因非常少。

您可能无法正常工作,因为您使用byte[]数组作为第一个参数,因此当从非托管端复制数据时,您将覆盖大量数据(可能您认为使用fixed将它们转换为指针?)。 类型必须匹配,以便结构匹配并正确复制数据。 此外,由于C#会自动重新排列一个最适合内存的结构,你可能不会放置数据。 这就是上面示例顶部的StructLayout所做的事情,它告诉编译器将结构保持为其定义的顺序。