我已经看到了可能的复制,但语义略有不同,所以到目前为止我还无法让它正常工作。我甚至不确定它是否真的可以与纯c函数指针风格相媲美,因为我已经在不同的项目中使用了它。
我有一个DLL,它定义了一个本机C++回调,如下所示:
class NativeClass
{
// Native Callback Handler class, internal definition
class Callback
{
public:
// Constructor
Callback() {}
// Destructor
virtual ~Callback() {}
// Callback functions
virtual void Handler() {}
};
SetCallback(Callback* p)
{
...
}
...然后,DLL通过以下函数使用并触发回调:
SetCallBack(NativeClass::Callback* p);因此,在编写C++/CLI包装器时,如何传递对公开此类回调处理程序的托管对象的引用。
这样的事情通常是不可能的,或者我必须如何正确地处理这个问题?现在,根据MSDN文档和其他答案,我尝试了以下几种方法:
typedef (__stdcall *NATIVE_CALLBACK)(void);
public delegate void ManagedCallback();
...
public ref class Wrapper
{
public:
Callback* _CBHandlerNative;
NativeClass* nc;
Wrapper()
{
_CBHandlerNative = new NativeClass::Callback();
_nc = new NativeClass();
// try assigning function pointer, but fails
IntPtr ip = Marshal::GetFunctionPointerForDelegate(gcnew ManagedCallback(this, &Wrapper::ToBeCalled));
_CBHandlerNative->Handler = static_cast<NATIVE_CALLBACK>(ip.ToPointer());
_nc->SetCallback(_CBHandlerNative);
}
// managed handler
void ToBeCalled()
{
...
}发布于 2014-06-19 08:47:38
我现在有了一个解决办法,似乎是正确的:
首先,我定义了一个本机代理类,用于保存回调:
public class CbProxy : Callback
{
public:
NATIVE_CALLBACK _cbHandler;
virtual void Handler()
{
if(_cbHandler != NULL)
_cbHandler();
}
}现在,我可以将托管委托附加到Handler代理,并将其传递给本机DLL。
public delegate void ManagedCallback ();
ManagedCallback^ mcb = gcnew ManagedCallback (this, &Wrapper::ToBeCalled);
IntPtr ip = Marshal::GetFunctionPointerForDelegate(mcb);
_pCbProxy->_cbHandler = static_cast<NATIVE_CALLBACK>(ip.ToPointer());
// ensure to keep a reference to the callback, otherwise it
// will be freed
GC::KeepAlive(mcb);
GC::KeepAlive(ip);
_nc->SetCallback(_pCbProxy);我不确定是否有更有效的方法,但这对我来说是一见钟情的。
https://stackoverflow.com/questions/24283612
复制相似问题