我想从 C++ 非托管代码调用 C# 委托。无参数委托工作正常,但有参数委托使我的程序崩溃

Posted

技术标签:

【中文标题】我想从 C++ 非托管代码调用 C# 委托。无参数委托工作正常,但有参数委托使我的程序崩溃【英文标题】:I want to call a C# delegate from C++ unmanaged code. A parameterless delegate works fine , but a delegate with parameters crashed my program 【发布时间】:2010-07-30 18:39:39 【问题描述】:

以下是来自未管理的 dll 的函数代码。它接受一个函数指针作为参数,并简单地返回被调用函数返回的值。

extern __declspec(dllexport) int  _stdcall callDelegate(int (*pt2Func)());
extern __declspec(dllexport) int  _stdcall callDelegate(int (*pt2Func)())

    int r = pt2Func();
    return r;

在托管 C# 代码中,我使用委托调用上面的 umanged 函数。

  unsafe public delegate int mydelegate( );

    unsafe public int delFunc()
    
             return 12;
    

    mydelegate d = new mydelegate(delFunc);
    int re = callDelegate(d);
   [DllImport("cmxConnect.dll")]
    private unsafe static extern int callDelegate([MarshalAs(UnmanagedType.FunctionPtr)] mydelegate d);

这一切都很好!但是如果我想让我的函数指针/委托接受参数,它会使程序崩溃。 因此,如果我按如下方式修改代码,我的程序就会崩溃。

修改后的非托管 c++ -

extern __declspec(dllexport) int  _stdcall callDelegate(int (*pt2Func)(int));
extern __declspec(dllexport) int  _stdcall callDelegate(int (*pt2Func)(int))

    int r = pt2Func(7);
    return r;

修改后的 C# 代码 -

unsafe public delegate int mydelegate( int t);

        unsafe public int delFunc(int t)
        
                 return 12;
        

        mydelegate d = new mydelegate(delFunc);
        int re = callDelegate(d);

【问题讨论】:

【参考方案1】:

函数指针的调用约定错误。让它看起来像这样:

 int (__stdcall * pt2Func)(args...)

【讨论】:

【参考方案2】:

所以这应该有效:

C++ DLL:

extern "C" __declspec(dllexport) void __stdcall doWork(int worktodo, int(__stdcall *callbackfunc)(int));

C#代码:

delegate int del (int work);    

[DllImport(@"mydll")]
private static extern void doWork(int worktodo, del callback); 

int callbackFunc(int arg) ... 

...

del d = new del(callbackFunc);
doWork(1000, d);

【讨论】:

以上是关于我想从 C++ 非托管代码调用 C# 委托。无参数委托工作正常,但有参数委托使我的程序崩溃的主要内容,如果未能解决你的问题,请参考以下文章

让非托管 c++ 代码调用调用 c# 代码的托管 c++ 代码

从 C# 如何调用需要 *VARIANT 参数的非托管 OLE 接口?

对“xxx”类型的已垃圾回收委托进行了回调。这可能会导致应用程序崩溃损坏和数据丢失。向非托管代码传递委托时,托管应用程序必须让这些委托保持活动状态,直到确信不会再次调用它们。 错误解决一例。(代码片段

从 C# 调用非托管 C++ VS 6.0 MFC dll

将回调参数从 C# 传递到非托管 C++

C#调用C++编写的DLL(非托管)