关于C# byte[]与struct的转换
来源:互联网 发布:广州口才培训 知乎 编辑:程序博客网 时间:2024/06/05 04:01
Some of the C# code I've been writing recently communicates via TCP/IP with legacy C++ applications. These applications use a raw packet format where C/C++ structures are passed back and forth.
Here is a simplified example of what the legacy code could look like:
#pragma pack(1)typedef struct{ int id; char[50] text;} MESSAGE;// Send a messageMESSAGE msg;msg.id = 1;strcpy(msg.text, "This is a test");send(socket, (char*)&msg);// Receive a messagechar buffer[100];recv(socket, buffer, 100);MESSAGE* msg = (MESSAGE*)buffer;printf("id=%d\n", msg->id);printf("text=%s\n", msg->text);
The problem I was faced with was how to receive and handle this kind of message in a C# application. One method is to use BitConverter and Encoding.ASCII to grab the data field by field. This is tedious, prone to errors and easy to break of modifications are made in the future.
A better method is to marshal the byte array to a C# structure. Here is an example of how to do that marshaling:
using System;using System.Runtime.InteropServices;[StructLayout(LayoutKind.Sequential, Pack=1)]struct Message{ public int id; [MarshalAs (UnmanagedType.ByValTStr, SizeConst=50)] public string text;}void OnPacket(byte[] packet){ GCHandle pinnedPacket = GCHandle.Alloc(packet, GCHandleType.Pinned); Message msg = (Message)Marshal.PtrToStructure( pinnedPacket.AddrOfPinnedObject(), typeof(Message)); pinnedPacket.Free();}
The GCHandle.Alloc call pins the byte[] in memory so the garbage collector doesn't mess with it. The AddrOfPinnedObject call returns an IntPtr pointing to the start of the array and the Marshal.PtrToStructure does the work of marshaling the byte[] to the structure.
If the actual structure data didn't start at the beginning of the byte array you would use the following assuming the structure data starts at position 10 of the array:
Message p = (Message)Marshal.PtrToStructure( Marshal.UnsafeAddrOfPinnedArrayElement(pinnedPacket, 10), typeof(Message));
[Serializable()]
public struct frame_t : ISerializable
{
//char数组,SizeConst表示数组的个数,在转换成
//byte数组前必须先初始化数组,再使用,初始化
//的数组长度必须和SizeConst一致
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
public char[] headers;
public int nbframe;
public double seqtimes;
public int deltatimes;
public int w;
public int h;
public int size;
public int format;
public ushort bright;
public ushort contrast;
public ushort colors;
public ushort exposure;
public byte wakeup;
public int acknowledge;
{
throw new Exception("The method or operation is not implemented.");
}
};
{
//struct转换为byte[]
public static byte[] StructToBytes(object structObj)
{
int size = Marshal.SizeOf(structObj);
IntPtr buffer = Marshal.AllocHGlobal(size);
try
{
Marshal.StructureToPtr(structObj, buffer, false);
byte[] bytes = new byte[size];
Marshal.Copy(buffer, bytes, 0, size);
return bytes;
}
finally
{
Marshal.FreeHGlobal(buffer);
}
}
//byte[]转换为struct
public static object BytesToStruct(byte[] bytes, Type strcutType)
{
int size = Marshal.SizeOf(strcutType);
IntPtr buffer = Marshal.AllocHGlobal(size);
try
{
Marshal.Copy(bytes, 0, buffer, size);
return Marshal.PtrToStructure(buffer, strcutType);
}
finally
{
Marshal.FreeHGlobal(buffer);
}
}
}
- 关于C# byte[]与struct的转换
- 关于C# byte[]与struct的转换
- C# struct byte[] 转换
- c# 结构体struct包含数与byte类型的转换(一)
- c# 结构体struct包含数与byte类型的转换(二)
- c# struct 变量 到 byte[] 变量的转换操作
- c# struct 变量 到 byte[] 变量的转换操作
- c# struct 变量 到 byte[] 变量的转换操作
- C# struct 和byte[] 相互转换
- C#中byte[]与string的转换
- C#中byte[]与string的转换
- C#中byte[]与string的转换
- C#中byte[]与string的转换
- C#中byte[]与string的转换
- C#中string与byte[]的转换
- C#中byte[]与string的转换
- C#中byte[]与string的转换
- C#中byte[]与string的转换
- linux中tar命令参数
- 查看linux服务器硬盘IO读写负载
- python --类方法、对象方法、静态方法
- POJ 1753 Flip Game (BFS)
- vim保存时报错:E382: Cannot write, 'buftype' option is set
- 关于C# byte[]与struct的转换
- 极大似然估计法
- Codeforces 570B__Simple Game
- Rxjava和RxAndroid系列(一)
- vs2010 生成目标文件 exe 改为 dll
- 软工视频总结Part One
- IOS开发页面间的传值 (代理和通知)
- poj3159
- Android自学笔记[1]---Android开发中常用的命令