C# VC++__C中的stdcall回调# 我正在研究一个C,GUI应用程序,需要调用C++ DLL。似乎除了一个特别的呼叫外,所有呼叫都正常工作。从C++头文件中,函数和回调签名是这样的: typedef void (__stdcall *LPFNDLL_RECEIVE_CALLBACK)(CANMsg*); USBCANPLUS_API CAN_STATUS __stdcall canplus_setReceiveCallBack( CANHANDLE handle, LPFNDLL_RECEIVE_CALLBACK cbfn );
根据阅读资料,我已设置并在课堂内部将呼叫包装为:C# VC++__C中的stdcall回调# 我正在研究一个C,GUI应用程序,需要调用C++ DLL。似乎除了一个特别的呼叫外,所有呼叫都正常工作。从C++头文件中,函数和回调签名是这样的: typedef void (__stdcall *LPFNDLL_RECEIVE_CALLBACK)(CANMsg*); USBCANPLUS_API CAN_STATUS __stdcall canplus_setReceiveCallBack( CANHANDLE handle, LPFNDLL_RECEIVE_CALLBACK cbfn );,c#,c++,callback,dllimport,C#,C++,Callback,Dllimport,根据阅读资料,我已设置并在课堂内部将呼叫包装为: [DllImport("USBCanPlusDllF.dll")] public static extern int canplus_setReceiveCallBack(int handle, CallbackDelegate callback); [UnmanagedFunctionPointerAttribute(CallingConvention.StdCall)] public delegate void CallbackDelega
[DllImport("USBCanPlusDllF.dll")]
public static extern int canplus_setReceiveCallBack(int handle, CallbackDelegate callback);
[UnmanagedFunctionPointerAttribute(CallingConvention.StdCall)]
public delegate void CallbackDelegate(ref CANMsg msg);
用作:
private static void callback(ref EASYSYNC.CANMsg msg)
{
Debug.Print(msg.id + ":" + msg.timestamp + ":" + msg.flags + ":" + msg.len + ":" + msg.data);
}
static EASYSYNC.CallbackDelegate del = new EASYSYNC.CallbackDelegate(callback);
private void button1_Click(object sender, EventArgs e)
{
int handle = EASYSYNC.canplus_Open(IntPtr.Zero, "1000", IntPtr.Zero, IntPtr.Zero, 0);
if(handle > 0)
{
int result = EASYSYNC.canplus_setReceiveCallBack(handle, del);
}
}
我知道处理C语言中的C++回调是很难的,并且在主题上已经读了一些,因此我有上面的代码。我的问题是我的代码命中int结果=。。。。整个程序都出去吃午饭了,这表明我可能在处理回调时仍有问题。有人能提供建议吗?我对此有点不确定,但您已将委托的调用约定指定为StdCall(必须是这样,因为C/C++代码中这么说),但您没有为canplus_setReceiveCallBack()dllimport函数声明这样做,执行以下操作时它是否有效:
[DllImport("USBCanPlusDllF.dll", CallingConvention=CallingConvention.StdCall)]
public static extern int canplus_setReceiveCallBack(int handle, CallbackDelegate callback);
正如我所说,我不确定,但这可能是问题所在。这是打字错误吗?我希望在
int result=
行的末尾看到(句柄,del)
而不是(句柄,回调)
。不要在回调中使用消息框,而是使用Debug.Print()。当垃圾收集器销毁委托时,您的代码也会爆炸,您需要将其保存在一个静态变量中。实际上是一个输入错误。我将在原帖中更正。@HansPassant根据您的评论所做的更正。同样的问题。此外,我确信回调尚未启动,因此问题与设置回调无关。您含糊不清的比喻性陈述表明程序从未从intresult=
行返回。是这样吗?根据MSDN,这似乎是在C#中传递函数指针的“正确”方式(同时,stdcall被认为是任何新委托类型的默认调用约定)。我假设CANHANDLE
实际上是一种兼容的4字节类型,但是您是否将C#项目(不是解决方案)构建为x86?如果是x64或任何CPU,委托将作为64位指针传递,并损坏堆栈。