• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

关于C# byte[]与struct的转换

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

转自:http://blog.chinaunix.net/uid-215617-id-2213082.html

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 message
MESSAGE msg;
msg.id = 1;
strcpy(msg.text, "This is a test");
send(socket, (char*)&msg);

// Receive a message
char 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));

 

 
以下为何丹写的,关于C# byte[]与struct的转换
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
        [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;
            #region ISerializable 成员
            public void GetObjectData(SerializationInfo info, StreamingContext context)
            {
                throw new Exception("The method or operation is not implemented.");
            }
            #endregion
        };
    public class Struct_Transform
    {
        //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);
            }
        }
    }

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
HtmlAgilityPack解析Html(C#爬虫利器)发布时间:2022-07-10
下一篇:
C#排序算法 之 插入排序发布时间:2022-07-10
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap