C#中结构体与字节流互相转换

因为程序必须要和C++开发的程序通信,而通信数据的是结构体的转化后的字节流,那么就要求C#能够顺利的将字节流转换为C#结构体。

 

  1. 定义与C++对应的C#结构体

     

    代码
    //C++结构体
    struct tagCheakUser
    {
    char userName[12];
    char pwd[32];
    }



    //对应的C#结构体
    [StructLayout( LayoutKind.Sequential,Pack=1)]
    public struct CheckUser
    {
    [MarshalAs( UnmanagedType.ByValTStr,SizeConst
    =12)]
    public string userName;
    [MarshalAs(UnmanagedType .ByValTStr,SizeConst
    =32)]
    public string pwd;
    }

     


    在C++的头文件定义中,使用了 #pragma pack 1 字节按1对齐,所以C#的结构体也必须要加上对应的特性,LayoutKind.Sequential属性让结构体在导出到非托管内存时按出现的顺序依次布局,而对于C++的char数组类型,C#中可以直接使用string来对应,当然了,也要加上封送的特性和长度限制。
  2. 结构体与byte[]的互相转换

     

    代码
    //convert structure T to byte[]
    public static byte[] ConvertStructToBytes(object objStruct)
    {
    //get the size of structure
    int size = Marshal.SizeOf(objStruct);
    //define buffer arrays
    byte[] buffer = new byte[size];
    //Alloc unmanaged memory and Copy structure to unmanaged memory
    IntPtr ipStruct = Marshal.AllocHGlobal(size);
    Marshal.StructureToPtr(objStruct, ipStruct,
    false);
    //Copy to the byte array
    Marshal.Copy(ipStruct, buffer, 0, size);
    //Free unmanaged memory
    Marshal.FreeHGlobal(ipStruct);
    return buffer;
    }

    //convert byte array to sturcture
    public static TR ConvertBytesToSturct<TR>(byte[] datas)
    {
    //get size of sturcture
    int size = Marshal.SizeOf(typeof(TR));
    //can not be convert
    if (datas.Length < size)
    {
    return default(TR);
    }
    //Alloc unmanaged memory and copy bytes data to memory
    IntPtr ipSturct = Marshal.AllocHGlobal(size);
    Marshal.Copy(datas,
    0, ipSturct, size);
    //Convert IntPtr to structure
    TR objStruct = (TR)Marshal.PtrToStructure(ipSturct, typeof(TR));
    //Free unmanaged memory
    Marshal.FreeHGlobal(ipSturct);
    return objStruct;
    }

  3. 测试

    代码
    static void Main(string[] args)
    {
    DataAPI.CheckUser ckUser
    = new DataAPI.CheckUser() { userName = "douzi",pwd="00" };
    byte[] bDatas = Converter.ConvertStructToBytes(ckUser);
    DataAPI.CheckUser ckUser1
    = Converter.ConvertBytesToSturct<DataAPI.CheckUser>(bDatas);
    Console.WriteLine(
    "User:{0} Pwd:{1}", ckUser1.userName, ckUser1.pwd);
    Console.ReadKey();
    }

     


 

这样,就能有效的和C++通讯了。

posted on 2014-02-26 20:55  鸿鹄168  阅读(366)  评论(0)    收藏  举报

导航