我通过USB将64字节数据包传递给微控制器。在微控制器C代码中,数据包具有结构
typedef union
{
unsigned char data[CMD_SIZE];
cmd_get_t get;
// plus more union options
} cmd_t;
与
typedef struct
{
unsigned char cmd; //!< Command ID
unsigned char id; //!< Packet ID
unsigned char get_id; //!< Get identifier
unsigned char rfu[3]; //!< Reserved for future use
union
{
unsigned char data[58]; //!< Generic data
cmd_get_adc_t adc; //!< ADC data
// plus more union options
} data; //!< Response data
} cmd_get_t;
和
typedef struct
{
int16_t supply;
int16_t current[4];
} cmd_get_adc_t;
在C#的PC端,我已经提供了一个函数,它将64字节数据包作为Byte []返回。该函数使用Marshal.Copy将接收的数据复制到Byte []数组中。然后我使用了表单
的C#结构[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct COMMAND_GET_ADC
{
public byte CommandID;
public byte PacketID;
public byte GetID;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=3)]
public byte[] RFU;
public short Supply;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=4)]
public short[] Current;
}
并再次使用Marshal.Copy将字节数组复制到结构中,以便我可以使用结构化数据,例如
COMMAND_GET_ADC cmd = (COMMAND_GET_ADC)RawDeserialize(INBuffer, 1, typeof(COMMAND_GET_ADC));
short supply = cmd.Supply;
与
public static object RawDeserialize(Byte[] rawData, int position, Type anyType)
{
int rawsize = Marshal.SizeOf(anyType);
if(rawsize > rawData.Length)
{
return null;
}
IntPtr buffer = Marshal.AllocHGlobal(rawsize);
Marshal.Copy(rawData, position, buffer, rawsize);
object retobj = Marshal.PtrToStructure(buffer, anyType);
Marshal.FreeHGlobal(buffer);
return retobj;
}
这只是感觉我正在制作大量的数据副本,并且它可能不是实现我想要的最有效的方式。我还需要将结构化数据转换回字节数组以获取设备的命令。我有一个方法使用相同的过程(即使用一个结构,然后将其序列化为一个字节数组,并将字节数组传递给写入函数)。
有更好的选择吗?
答案 0 :(得分:2)
如果可以使用不安全的代码,可以使用'fixed'关键字将字节数组转换为指向结构的指针。
答案 1 :(得分:2)
如果您自己调用本机DLL,则可以定义DllImport-s,以便它们直接返回并接受COMMAND_GET_ADC - 前提是您已正确表示结构。框架本身应该照顾它。
如果你必须使用提供给你的方法使用的字节数组 - 那么我不知道,我从来没有这样的约束。我总是尝试以与本机dll相同的方式表示我的互操作性数据,我不记得我遇到了重大问题。
编辑:
[StructLayout(LayoutKind.Explicit)]
public struct COMMAND_GET
{
[FieldOffset(0)]
public byte CommandID;
[FieldOffset(1)]
public byte PacketID;
[FieldOffset(2)]
public byte GetID;
[FieldOffset(3)]
[MarshalAs(UnmanagedType.ByValArray, SizeConst=3)]
public byte[] RFU;
[FieldOffset(6)]
public ADC_Data Adc_data;
[FieldOffset(6)]
public SomeOther_Data other_data;
[FieldOffset(6)]
....
}
[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct ADC_Data
{
public short Supply;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=4)]
public short[] Current;
}
基本上你有FieldOffset(6)你在cmd_get_t
中创建了像union union这样的联合