笔记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就不会回收此字段以及此字段所在的类对象。