最近经常用到与C++相互调用,这就涉及到两种语言的数据类型互相转换
不知道的时候就到处查找资料,今天又遇到了C++中TCHAR转换成C# string
一开始不懂,直接找资料转换成以下代码
C++结构体定义:
//登录命令
#define MDM_MB_LOGON 100 //广场登录
#define SUB_MB_LOGON_VISITOR 5 //游客登录
#define LEN_MACHINE_ID 33 //序列长度
#define LEN_MOBILE_PHONE 12 //移动电话
//游客登录
struct CMD_MB_LogonVisitor
{
//系统信息
WORD wModuleID; //模块标识
DWORD dwPlazaVersion; //广场版本
BYTE cbDeviceType; //设备类型
//连接信息
TCHAR szMachineID[LEN_MACHINE_ID]; //机器标识
TCHAR szMobilePhone[LEN_MOBILE_PHONE]; //电话号码
};
翻译成C#结构体:
public struct CMD_MB_LogonVisitor
{
public ushort wModuleID;
public uint dwPlazaVersion;
public byte cbDeviceType;
public string szMachineID;
public string szMobilePhone;
}
//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 type)
{
int size = Marshal.SizeOf(type);
IntPtr buffer = Marshal.AllocHGlobal(size);
try
{
Marshal.Copy(bytes, 0, buffer, size);
return Marshal.PtrToStructure(buffer, type);
}
finally
{
Marshal.FreeHGlobal(buffer);
}
}
通过StructToBytes转换成byte[]大小为32
服务器解析后数据不对,后面两个字符串长度不匹配
经过百度后,C++中TCHAR 要加[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
最终结果:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct CMD_MB_LogonVisitor
{
/// WORD->unsigned short
public ushort wModuleID;
/// DWORD->unsigned int
public uint dwPlazaVersion;
/// BYTE->unsigned char
public byte cbDeviceType;
/// TCHAR[33]
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 33)]
public string szMachineID;
/// TCHAR[12]
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 12)]
public string szMobilePhone;
}
这个代码不是自己写的,是生成的
在查找问题过程中得知P/Invoke Interop Assistant这个工具,对不熟悉C++的太有用了
输入C++结构体定义,自动生成C#代码,支持VB,C#