C#引用C++接口取值问题
问题分类
不同程序语言的动态库引用问题。
问题描述
C++和C#库的接口返回值和参数类型的映射关系。
原因分析
C++和C#的类型有区别,C#中把地址的概念弱化了,对于引用类型的值C#要如何取值。
解决方案
可以通过IntPtr或者使用回调取值,如下:
C++库接口:
typedef void(STD_CALL* infoSizeCB)(string savedLen);
char* GetInfo(int portnum, int info_type, size_t* info_size = 0);
C#接口:
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate void InfoSizeCB(ulong savedLen);
[DllImport(SdkPath, CharSet = CharSet.Auto)]
public static extern IntPtr GetInfo(int portnum, int info_type, InfoSizeCB cb = null);
C++指针类型在C#中使用IntPtr与之对应,调用GetInfo函数取到地址后C#需要调用特定接口获取。
IntPtr inptr = GetInfo(_portID, nType, (len) => { });
string info = Marshal.PtrToStringAnsi(inptr);
这里对IntPtr取不同类型数据的做一些拓展:
Marshal.PtrToStructure 取结构体类型数据
Marshal.PtrToStringAnsi 取字符串类型数据(Ansi )
Marshal.PtrToStringAuto 取字符串类型数据(Autofont)
Marshal.PtrToStringBSTR 取字符串类型数据(BSTR)
Marshal.PtrToStringUni 取字符串类型数据(Unicode)
如果需要申请内存存储数据可以使用以下方式
int len = 100;
IntPtr ptr = Marshal.AllocHGlobal(len);
int nIndex = 0;
ASCIIEncoding strData = new ASCIIEncoding();
//将字符串转换为ASCII编码的字节数字
byte[] strBytes = strData.GetBytes("TEST");
Marshal.Copy(strBytes.ToArray(), nIndex, ptr, len);
Marshal.FreeHGlobal(ptr);