C#读取C++结构体

工作中遇到C++写的程序将结构体存储到Redis中。然后使用C#读取。其中有几个需要注意的坑。

1.Struct上的StructLayout中的Pack

  在C#中定义的struct一定要和C++中的对应上 

  [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]

  其中pack 对应C++中De#program pack()

  附结构体转换代码:

 1   public StructType ConverBytesToStructure<StructType>(byte[] bytesBuffer)
 2         {
 3             // 检查长度。
 4             if (bytesBuffer.Length != Marshal.SizeOf(typeof(StructType)))
 5             {
 6                 throw new ArgumentException("bytesBuffer参数和structObject参数字节长度不一致。");
 7             }
 8 
 9             IntPtr bufferHandler = Marshal.AllocHGlobal(bytesBuffer.Length);
10             for (int index = 0; index < bytesBuffer.Length; index++)
11             {
12                 Marshal.WriteByte(bufferHandler, index, bytesBuffer[index]);
13             }
14             StructType structObject = (StructType)Marshal.PtrToStructure(bufferHandler, typeof(StructType));
15             Marshal.FreeHGlobal(bufferHandler);
16             return structObject;
17         }

2.嵌套结构体数组的定义

 当一个结构体中含有另一个结构体数组时,使用如下的定义

     

[MarshalAs(UnmanagedType.ByValArray, SizeConst = 18)]
public StructB[] m_Info;

 

3.字符编码的转换(宽窄字符集的问题)

 采用上述StructLayout中的编码方式和在C++中的一样

 在C++中 我将Const char*为了将汉字转化成PB的UTF-8

   

inline string GBKToUTF8(const char* cchar)
{
    std::string strs(cchar);
    string strOutUTF8 = "";
    WCHAR * str1;
    int n = MultiByteToWideChar(CP_ACP, 0, strs.c_str(), -1, NULL, 0);
    str1 = new WCHAR[n];
    MultiByteToWideChar(CP_ACP, 0, strs.c_str(), -1, str1, n);
    n = WideCharToMultiByte(CP_UTF8, 0, str1, -1, NULL, 0, NULL, NULL);
    char * str2 = new char[n];
    WideCharToMultiByte(CP_UTF8, 0, str1, -1, str2, n, NULL, NULL);
    strOutUTF8 = str2;
    delete[]str1;
    str1 = NULL;
    delete[]str2;
    str2 = NULL;
    return strOutUTF8;
}

  在C#端将转化过的字符串无论使用哪个字符集转都显示乱码。最后调用了C++的方法。

  [DllImport("kernel32.dll")]

        private static extern int MultiByteToWideChar(int CodePage, int dwFlags, string lpMultiByteStr,

                           int cchMultiByte, [MarshalAs(UnmanagedType.LPWStr)]string lpWideCharStr, int cchWideChar);

 public string MByteToWChar(string content, int toEncode)
        {

            //字符编码转换 gb2312:936   utf-8:65001  big5:950  latin1:1252

            int len = MultiByteToWideChar(toEncode, 0, content, -1, null, 0);

            char[] temp = new char[len];

            string content1 = new string(temp);

            MultiByteToWideChar(toEncode, 0, content, -1, content1, len);

            return content1;

        }

 

posted @ 2019-03-13 20:28  胖胖仔  阅读(3572)  评论(0编辑  收藏  举报