C#引用C++接口取值问题

发表于2020-07-22
评论0 5.7k浏览

问题分类

不同程序语言的动态库引用问题。
 

问题描述

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

  • 允许他人重新传播作品,但他人重新传播时必须在所使用作品的正文开头的显著位置,注明用户的姓名、来源及其采用的知识共享协议,并与该作品在磨坊上的原发地址建立链接
  • 可对作品重新编排、修改、节选或者以作品为基础进行创作和发布
  • 可将作品进行商业性使用

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引

标签: