2014-06-18 24 views
2

我已经看到可能的重复,但语义略有不同,所以直到现在我还没有得到它的工作。我甚至不确定它与真正的c函数指针风格相当,我已经在不同的项目中使用过。如何处理托管包装中的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包装器,我如何传递一个引用到一个托管对象,暴露这样的回调处理程序。

是这样的一般不可能或者我将如何正确处理该 ?

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() 
{ 
    ... 
} 
+0

有一个关于MSDN的文档[文档](http://msdn.microsoft.com/en-us/library/367eeye0%28v=vs.100%29.aspx) – Jairo

+0

@Jairo:看起来很有前途,但它也适用于回调对象?我只看到一个回调函数,而不是具有多个函数的对象。或者,我是否简单地将指针指定给回调对象中每个虚函数的包装函数? –

回答

1

我现在有一个解决方案,这似乎是正常工作:

首先,我定义的本地 我下面现在根据MSDN文档和其他SO答案尝试用于保存回调的代理类:

public class CbProxy : Callback 
{ 
public: 
    NATIVE_CALLBACK _cbHandler; 

    virtual void Handler() 
    { 
     if(_cbHandler != NULL) 
      _cbHandler(); 
    } 
} 

现在我可以将托管代理附加到处理程序代理并将其传递给本机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); 

我不确定是否有更有效的方法,但这对我来说目前是一见钟情。

相关问题