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根据您的评论所做的更正。同样的问题。此外,我确信回调尚未启动,因此问题与设置回调无关。您含糊不清的比喻性陈述表明程序从未从int
result=
行返回。是这样吗?根据MSDN,这似乎是在C#中传递函数指针的“正确”方式(同时,stdcall被认为是任何新委托类型的默认调用约定)。我假设
CANHANDLE
实际上是一种兼容的4字节类型,但是您是否将C#项目(不是解决方案)构建为x86?如果是x64或任何CPU,委托将作为64位指针传递,并损坏堆栈。