博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
关于C# byte[]与struct的转换
阅读量:6395 次
发布时间:2019-06-23

本文共 3449 字,大约阅读时间需要 11 分钟。

转自:

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));

 

 
以下为何丹写的,关于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);
            }
        }
    }

转载地址:http://mnoha.baihongyu.com/

你可能感兴趣的文章
老程序员的下场
查看>>
IOS“The run destination My Mac 64-bit is not valid
查看>>
log4j:WARN Please initialize the log4j system p...
查看>>
Mybatis架构设计及源码分析-Mybatis配置文件初始化全过程
查看>>
Mac下安装Wget
查看>>
怎样取得 VirtualBox 虚拟机器 ip
查看>>
Thinkphp项目结合JS消息提醒
查看>>
Golang import
查看>>
SQL Server 数据库分离与附加(图文教程)
查看>>
PHP的json_encode中文被转码的问题
查看>>
flutter -------- ListView的使用
查看>>
Jmeter用法记录---While Controller
查看>>
iOS开发小技巧总结1(iOS7 企业证书部署等问题)
查看>>
Speex manul中文版
查看>>
php将小写金额改成大写,万亿以下应该都没问题
查看>>
javascript推荐书籍
查看>>
ubuntu jcaptcha本地发布时验证码无法显示
查看>>
试论Java异常
查看>>
HTTP协议头部与Keep-Alive模式详解
查看>>
虚拟机&容器技术
查看>>