[Dllimport("c++库名", CallingConvention = CallingConvention.StdCall)]
private static extern void method_exsample([MarshalAs(UnmanagedType.LPStr)] string url, [MarshalAs(UnmanagedType.LPStr)] string str, IntPtr context, IntPtr bytes, int length);
-
extern关键字
修饰符用于声明在外部实现的方法。extern 修饰符的常见用法是在使用 Interop 服务调入非托管代码时与 Dllimport 属性一起使用;在这种情况下,该方法还必须声明为 static
-
Dllimport特性
[Dllimport(“c++库名”, CallingConvention = CallingConvention.StdCall)]
CallingConvention 调用约定,决定了参数入栈的顺序,从左往右还是从右往左,出栈方式之类的。根据C++导出的设置来处理
-
MarshalAs特性
[MarshalAs(UnmanagedType.LPStr)]
在C++中 字符串或者某类型数组是char* 或者某类型的指针
这个特性可以帮忙将指针转为C#类型 C++ char*->C# string
如果不用这个特性,参数类型就写IntPtr,用到的时候Marshal.PtrToStringAnsi(ptr)可以转string,也是差不多的效果。
C#对象属于托管堆,有垃圾回收机制管理内存。C++的内存是非托管的,当C++使用C#对象时,有可能这个对象被GC回收了。为了避免在C++使用期间被回收,需要使用GCHandle将它“钉住”,让GC暂时不要回收。用完也要记得解除这个钉子。
GCHandle gcHandler = GCHandle.Alloc(C#对象, GCHandleType.Pinned); gcHandler.Free();//C++结束使用后,释放它
除了基础数据类型,其他C#类型对象传递到C++,我们都以IntPtr的形式,这两种方式都可以获得IntPtr。
GCHandler.ToIntPtr(gcHandler); gcHandler.AddrOfPinnedObject();C++回调C#方法
C++有函数指针,对C#来说就是委托。
我们要将C#方法注册到C++,就定义一个跟C++函数指针相同的委托
C++注册C#函数的方法
[Dllimport("c++库名", CallingConvention = CallingConvention.StdCall)]
private static extern void cpp_callback_register(csharp_delegate cb, Intptr context);
C#定义委托
public delegate int csharp_delegate (IntPtr cpp_ptr, int size, IntPtr context);
C#被回调的方法
标记MonoPInvokeCallback特性
[AOT.MonoPInvokeCallback(typeof(csharp_delegate))]
static void CSharp_Callback_Method(IntPtr cpp_ptr,int size, IntPtr context)
{
if(cpp_ptr != Intptr.Zero)//如果C++指针不为空
{
//...
}
}
IntPtr转回C#对象
如果将C#对象作为C++回调的上下文,我们将C#对象转为IntPtr传入C++,回调的时候也是IntPtr
GCHandle.FromIntPtr(ptr).Target as C#对象
还有一些用法,根据具体使用的时候查阅文档就可了。
Marshal.Copy(IntPtr.Add(ptr, recvSize), bytes, 0, copySize);



