通过 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#)的主要内容,如果未能解决你的问题,请参考以下文章
java是通过值传递,也就是通过拷贝传递——通过方法操作不同类型的变量加深理解