将复杂结构编组到 C#
Posted
技术标签:
【中文标题】将复杂结构编组到 C#【英文标题】:Marshalling complex struct to c# 【发布时间】:2015-05-26 16:47:25 【问题描述】:我仍在努力将一个相当复杂的结构从 c++ 编组到 c#。
c++中的结构如下:
typedef struct
DWORD Flags;
DWORD TimeCode;
DWORD NodeMoving;
Matrix NodeRots[NUM_GYROS];
Vector Position;
DWORD ContactPoints;
float channel[NUM_CHANNELS];
Frame;
矢量:
typedef struct
union
struct
float x, y, z;
;
float Array[3];
;
Vector;
矩阵:
typedef struct
union
struct
float xx, xy, xz; //This row is the right vector
float yx, yy, yz; //This row is the up vector
float zx, zy, zz; //This row is the forward vector
;
float Array[3][3]; //[row][col]
;
Matrix;
这是我在 c# 中所拥有的:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public unsafe struct Matrix
public float xx;
public float xy;
public float xz;
public float yx;
public float yy;
public float yz;
public float zx;
public float zy;
public float zz;
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public unsafe struct Vector
public float x;
public float y;
public float z;
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public unsafe struct Frame
public uint Flags;
public uint TimeCode;
public uint NodeMoving;
public fixed byte NodeRots[NUM_GYROS];
public Vector Position;
public uint ContactPoints;
public fixed float channel[CHANNEL_ARRAY_SIZE];
public unsafe float[] Channel
get
fixed (float* ptr = channel)
float[] array = new float[CHANNEL_ARRAY_SIZE];
Marshal.Copy((IntPtr)ptr, array, 0, CHANNEL_ARRAY_SIZE);
return array;
public unsafe Matrix[] nodeRots
get
fixed (byte* ptr = NodeRots)
IntPtr ptr2 = (IntPtr)ptr;
Matrix[] array = new Matrix[NUM_GYROS];
for (int i = 0; i < array.Length; i++)
array[i] = (Matrix)Marshal.PtrToStructure(ptr2, typeof(Matrix));
IntPtr oldptr = ptr2;
ptr2 = new IntPtr(oldptr.ToInt32() + Marshal.SizeOf(typeof(Matrix)));
return array;
Frame 结构的值 Flags、TimeCode、NodeMoving 和 NodeRots 已经正确传递。成员职位、联系点和渠道未正确编组。我想我必须对职位成员做点什么,但我真的不知道到底是什么错误。
【问题讨论】:
NodeRots 是从哪里来的?不应该是矩阵吗? 或至少Num_Gyros * 9 * 4
我认为它应该,但是当我将它声明为固定矩阵时,我得到一个编译错误:DLLHelper.Frame.nodeRots':固定大小缓冲区类型必须是以下之一:bool、byte、short , int, long, char, sbyte, ushort, uint, ulong, float 或 double
【参考方案1】:
我已经告诉过你了。您不能将fixed byte
用作问题的通用解决方案。
这个
public fixed byte NodeRots[NUM_GYROS];
必须
public fixed Matrix NodeRots[NUM_GYROS];
然后这个:
Marshal.Copy((IntPtr)ptr, array, 0, CHANNEL_ARRAY_SIZE)
必须
Marshal.Copy((IntPtr)ptr, array, 0, CHANNEL_ARRAY_SIZE * sizeof(float));
那么对于nodeRots
getter,您实际上并不需要Marshal.PtrToStructure
,因为您的结构可以直接编组。
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public unsafe struct Frame
public uint Flags;
public uint TimeCode;
public uint NodeMoving;
public fixed float nodeRots[NUM_GYROS * 9];
public Vector Position;
public uint ContactPoints;
public fixed float channel[CHANNEL_ARRAY_SIZE];
public unsafe float[] Channel
get
fixed (float* ptr = channel)
float[] array = new float[CHANNEL_ARRAY_SIZE];
Marshal.Copy((IntPtr)ptr, array, 0, CHANNEL_ARRAY_SIZE * sizeof(float));
return array;
public unsafe Matrix[] NodeRots
get
fixed (float* ptr = nodeRots)
Matrix[] array = new Matrix[NUM_GYROS];
for (int i = 0, y = 0; i < array.Length; i++, y += 9)
array[i].xx = ptr[y + 0];
array[i].xy = ptr[y + 1];
array[i].xz = ptr[y + 2];
array[i].yx = ptr[y + 3];
array[i].yy = ptr[y + 4];
array[i].yz = ptr[y + 5];
array[i].zx = ptr[y + 6];
array[i].zy = ptr[y + 7];
array[i].zz = ptr[y + 8];
return array;
【讨论】:
我无法将 NodeRots 声明为固定矩阵,因为我收到编译错误:DLLHelper.Frame.nodeRots':固定大小缓冲区类型必须是以下之一:bool、byte、short、int、 long、char、sbyte、ushort、uint、ulong、float 或 double @user1643687 对...再试一次。修改为固定的 float[] 数组,并更改了 NodeRots 属性 @xanatos 也许你可以帮我解决我刚刚问的问题? ***.com/questions/30592485/…以上是关于将复杂结构编组到 C#的主要内容,如果未能解决你的问题,请参考以下文章
创建要在 C# 中编组的 C++ Dll 的最佳实践 [关闭]