首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在托管包装器中处理C++本机回调类

如何在托管包装器中处理C++本机回调类
EN

Stack Overflow用户
提问于 2014-06-18 10:49:50
回答 1查看 2.9K关注 0票数 2

我已经看到了可能的复制,但语义略有不同,所以到目前为止我还无法让它正常工作。我甚至不确定它是否真的可以与纯c函数指针风格相媲美,因为我已经在不同的项目中使用了它。

我有一个DLL,它定义了一个本机C++回调,如下所示:

代码语言:javascript
复制
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通过以下函数使用并触发回调:

代码语言:javascript
复制
SetCallBack(NativeClass::Callback* p);

因此,在编写C++/CLI包装器时,如何传递对公开此类回调处理程序的托管对象的引用。

这样的事情通常是不可能的,或者我必须如何正确地处理这个问题?现在,根据MSDN文档和其他答案,我尝试了以下几种方法:

代码语言:javascript
复制
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()
{
  ...
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-06-19 08:47:38

我现在有了一个解决办法,似乎是正确的:

首先,我定义了一个本机代理类,用于保存回调:

代码语言:javascript
复制
public class CbProxy : Callback
{
public:
   NATIVE_CALLBACK _cbHandler;

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

现在,我可以将托管委托附加到Handler代理,并将其传递给本机DLL。

代码语言:javascript
复制
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);

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24283612

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档