通过 Marshal.GetFunctionPointerForDelegate 从本机 (C++) 线程调用托管函数 (C#)

Posted

技术标签:

【中文标题】通过 Marshal.GetFunctionPointerForDelegate 从本机 (C++) 线程调用托管函数 (C#)【英文标题】:Calling a managed function (C#) via Marshal.GetFunctionPointerForDelegate from a native (C++) thread 【发布时间】:2015-08-18 01:21:28 【问题描述】:

我正在使用Marshal.GetFunctionPointerForDelegate 来获取指向本机函数的函数指针。然后我通过常规的 DllImport 机制将此函数指针传递给一些非托管代码。我将其用于回调;本机代码回调托管 (C#) 代码。只要回调发生在同一个线程上,一切正常。如果我尝试从通过CreateThread 创建的线程调用托管函数,则会失败。

是否可以简单地通过 GetFunctionPointerForDelegate 返回的函数指针从本机线程回调托管代码?

C#:

//in class definition
[DllImport("SomeDll")]
public static extern void SetCallback(System.IntPtr function);

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public void delegate SomeDelgateType();

public SomeDelgateType OnCallback;

//a function to implement the callback
public void Callback()



//inside a setup function
OnCallback = new SomeDelgateType(Callback);
SetCallback(Marshal.GetFunctionPointerForDelegate(OnCallback);

当我从 C++ 调用函数指针时出现问题。如果它在使 SetCallback 函数一切正常的原始线程上。如果我使用 CreateThread 创建本机线程,然后尝试通过指针调用该函数,则会出现以下异常:

    Unhandled exception at 0x76674598 (KernelBase.dll) in      MissionControl.exe: 0xE0434352 (parameters: 0x80070057, 0x00000000, 0x00000000, 0x00000000, 0x73DB0000).

使用以下堆栈跟踪:

        KernelBase.dll!_RaiseException@16()    Unknown
        clr.dll!RaiseTheExceptionInternalOnly(class Object *,int,int)   Unknown
        clr.dll!IL_Throw(class Object *)    Unknown
        02bbc34b()  Unknown
        [Frames below may be incorrect and/or missing]  
        [External Code] 
        native_function_on_different_thread();

【问题讨论】:

【参考方案1】:

事实证明,您实际上可以从非托管线程调用。问题是,如果您正在调试托管应用程序,回调中的断点实际上不会在调试器中运行,但您的代码仍将被执行。为了让你的断点工作,你需要启用“本地代码调试”(即使你的断点在托管代码中!)通过转到 Project -> Properties -> 调试 -> 启用本机代码调试

【讨论】:

以上是关于通过 Marshal.GetFunctionPointerForDelegate 从本机 (C++) 线程调用托管函数 (C#)的主要内容,如果未能解决你的问题,请参考以下文章

下拉框多选框单选框 通过TagHelper绑定数据

酶:测试孩子通过安装渲染失败,但通过浅时通过

java是通过值传递,也就是通过拷贝传递——通过方法操作不同类型的变量加深理解

通过代码进行 Spring 配置与通过注释进行配置

如何理解“不要通过共享内存来通信,而应该通过通信来共享内存”?

通过邮递员通过 API 使用 Rails 主动存储上传文件(.pdf、.jpg 等)? (不通过 Rails 视图)