Unity技术QQ群:484275915,有需要可以加群相互探讨
#C#调用C++返回指针参数
##用IntPtr接收返回
下面是引入DLL的代码片段:
[DllImport("BthExports")]
public extern static IntPtr BthGetName(UInt64 ullAddr);
其返回的内容为一个Uint64的数组,我们可以用“IntPtr”来代替这个C++方法体返回的指针,我们可以先来看一下“IntPtr”的定义:“IntPtr用于表示指针或句柄的平台特定类型,此类型对多线程操作是安全的。C#中的IntPtr类型称为“平台特定的整数类型”,它们用于本机资源,如窗口句柄。资源的大小取决于使用的硬件和操作系统,但其大小总是足以包含系统的指针(因此也可以包含资源的名称)。”以上两段加黑加粗的文字已经告诉我们“Intptr”这个类型是可以在C#中安全的接收指针的一个类型了。毕竟是C#原生的标记好的安全类型,所以在日常的使用过程中,我个人更加推荐使用此种类型来接收非托管代码返回的指针。
IntPtr tempAddrName = BthGetName(allAddrs[i]);//接收返回的数组
string m_strAddrName = Marshal.PtrToStringAnsi(tempAddrName);//将其转换为字符串
当调用此Dll接收到返回的IntPtr类型的变量之后,我们需要使用这个函数进行一下字符串的转换:
Marshal.PtrToStringAnsi
这个函数是C#自带的,在添加“System.Runtime.InteropServices”引用之后可以使用,这样使用“IntPtr”类型就可以拿到非托管代码里面返回的字符串了。
##用指针接收返回
[DllImport("BthExports")]
unsafe public extern static char* BthGetAddr();
当打算直接用非安全语言在托管代码中去操作非托管代码的指针的时候,只需要在添加的这段引用之前加上unsafe关键字即可,unsafe可以用来修饰类、类的成员函数、类的全局变量,但不能用来修饰类成员函数内的局部变量。
#C#向C++传入指针参数
##传入数组
当传入数组的时候,可以这样直接传入:
[DllImport("BthExports")]
public extern static void BthGetAddr([MarshalAs(UnmanagedType.LPArray, SizeConst = 6)]UInt64[] pAddr);
##传入指针
在C#脚本中定义Dll的函数体的时候可以直接如下定义:
[DllImport("BthExports")]
unsafe public extern static void BthGetAddr([MarshalAs(UnmanagedType.LPArray, SizeConst = 10)]UInt64* pAddr);
其中:
MarshalAs.UnmanagedType.LPArray
是指向 C 样式数组的第一个元素的指针。当从托管到非托管进行封送处理时,该数组的长度由托管数组的长度确定。当从非托管到托管进行封送处理时,将根据 System.Runtime.InteropServices.MarshalAsAttribute.SizeConst和 System.Runtime.InteropServices.MarshalAsAttribute.SizeParamIndex 字段确定该数组的长度(其长度为字符数,不是字节长度),当需要区分字符串类型时,还可以后跟数组中元素的非托管类型。
在Unity中使用“unsafe”“fixed”等非安全代码声明关键字的时候,我们发现在编译器中会报错,从而导致程序无法运行,这时我们需要在工程中加入一个文件,这个文件我们可以自己创建,Windows版本创建流程如下所示: