说起结构体与byte[]之间的转换,主要是为了能够让结构体通过socket进行传输,实现通信。
首先我们来看看C下面的一个结构体:
1
2
3
4
5
6
7
|
#prgrma pack(1)
struct pack
{
uint8_t type;
uint32_t lenght;
}
#prgrma pack()
|
这里我们需要字节对齐,以保证两个平台之间数据传输的正确性。
1
2
3
4
5
6
7
|
[Serializable]
[StructLayout(LayoutKind.Sequential,Pack=1)]
public struct pack
{
byte type;
int lenght;
}
|
下面上一张表,以表示在C#下面的数据类型与C/C++的不同:
如果我们是在C/C++下面使用send/recv接收数据的话,直接将指针传递给函数就可以了,但是在c#下面显然行不通,c#的socket.send方法与socket.recive方法都只能接受或者发送byte[]类型,如果我们需要发送结构体,就需要将结构体转换为byte[]类型或者将字节数组转换为我们需要的结构体。
我们可以编写两个函数来实现两种不同类型的转换,在编写的时候我们需要:
1
|
using System.Runtime.InteropServices;
|
下面我们就来写这两个函数,StructToBytes和BytesToStruct:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
public byte[] StructToBytes(object obj)
{
int size = Marshal.SizeOf(obj);
byte[] bytes = new byte[size];
IntPtr structptr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(obj, structptr, false);
Marshal.Copy(structptr, bytes, 0, size);
//Marshal.FreeHGlobal(structPtr);
return bytes;
}
public object BytesToStruct(byte[] bytes,Type type)
{
int size = Marshal.SizeOf(type);
if (size > bytes.Length)
{
//返回空
return null;
}
IntPtr structPtr = Marshal.AllocHGlobal(size);
//将byte数组拷到分配好的内存空间
Marshal.Copy(bytes, 0, structPtr, size);
//将内存空间转换为目标结构
object obj = Marshal.PtrToStructure(structPtr, type);
//释放内存空间
Marshal.FreeHGlobal(structPtr);
//返回结构
return obj;
}
|