C#调用C dll一些走过坑的笔记

笔记1:

c dll的call convention 是cdecl ,弄了一个CallBack,供外部调用。

C#方面 在debug模式下,委托不加UnmanagedFunctionPointer是正常的,在release模式下不加UnmanagedFunctionPointer不行,加上UnmanagedFunctionPointer才正常。

错误的写法:

internal delegate void Internal_Can_ReceiveCallBack_t(IntPtr device, CAN_RxPacket_t rx);
internal delegate void Internal_Can_TxErrorCallBack_t(IntPtr device, CAN_TxPacket_t tx);
internal delegate void Internal_Can_ControlUnitStatusUpdateCallBack_t(IntPtr device, CAN_ControlUnitStatus_t status);

正确的写法:

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    internal delegate void Internal_Can_ReceiveCallBack_t(IntPtr device, CAN_RxPacket_t rx);
    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    internal delegate void Internal_Can_TxErrorCallBack_t(IntPtr device, CAN_TxPacket_t tx);
    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    internal delegate void Internal_Can_ControlUnitStatusUpdateCallBack_t(IntPtr device, CAN_ControlUnitStatus_t status);

总结:

以后调用一切的C/C++ dll  任何函数 任何委托 全部显式写出  CallingConvention

笔记2:

有如下函数:

[DllImport("my.dll",CallingConvention= CallingConvention.Cdecl,EntryPoint = "setCallBack")]
private static extern void setCallBack(myCallBack_t callback);

相当于C#写CallBack供 C dll调用, 那么在C#方面一定要搞一个委托的实例字段 将C#方法付给这个实例,再将实例传给C dll

错误写法:

C#:
public void foo()
{
......
}

setCallBack(foo);

正确的写法:

public void foo()
{
......
}
private myCallBack_t internalMyCallBack;

internalMyCallBack=foo;
setCallBack(internalMyCallBack);

原因参照MDA, 百度搜一下callbackOnCollectedDelegate ,也很简单,搞一个字段,将函数赋给这个字段的话,字段在相当于一直在引用这个委托的实例,GC就不会回收这个委托的实例,如果字段所在的类对象在程序运行期间 一直存在,那么 GC就不会回收此字段以及此字段所在的类对象。

猜你喜欢

转载自blog.csdn.net/snikeguo/article/details/86687116