2008-10-02 72 views
11

我在本地C++类中使用boost :: signal,现在我正在使用C++/CLI编写.NET包装器,以便我可以将本机C++回调公开为.NET事件。当我尝试使用boost :: bind来获取我的托管类的成员函数的地址时,我得到编译器错误3374,说我不能接受成员函数的地址,除非我正在创建一个委托实例。有谁知道如何使用boost :: bind绑定托管类的成员函数?如何在C++/CLI中使用boost :: bind绑定托管类的成员

为了澄清,下面的示例代码会导致编译器错误3374:

#include <boost/bind.hpp> 

public ref class Managed 
{ 
public: 
    Managed() 
    { 
     boost::bind(&Managed::OnSomeEvent, this); 
    } 

    void OnSomeEvent(void) 
    { 
    } 
}; 

回答

10

当你的答案有效时,它会将你的一些实现暴露给世界(Managed :: OnSomeEvent)。如果你不希望人们能够通过调用OnSomeEvent(),您可以按以下步骤更新您的托管类不管三七二十一提高OnChange事件(基于this advice):

public delegate void ChangeHandler(void); 
typedef void (__stdcall *ChangeCallback)(void); 

public ref class Managed 
{ 
public: 
    Managed(Native* Nat); 
    ~Managed(); 

    event ChangeHandler^ OnChange; 

private: 
    void OnSomeEvent(void); 
    Native* native; 
    Callback* callback; 
    GCHandle gch; 
}; 

Managed::Managed(Native* Nat) 
: native(Nat) 
{ 
    callback = new Callback; 

    ChangeHandler^ handler = gcnew ChangeHandler(this, &Managed::OnSomeEvent); 
    gch = GCHandle::Alloc(handler); 
    System::IntPtr ip = Marshal::GetFunctionPointerForDelegate(handler); 
    ChangeCallback cbFunc = static_cast<ChangeCallback>(ip.ToPointer()); 

    *callback = native->RegisterCallback(boost::bind<void>(cbFunc)); 
} 

Managed::~Managed() 
{ 
    native->UnregisterCallback(*callback); 
    delete callback; 
    if (gch.IsAllocated) 
    { 
     gch.Free(); 
    } 
} 

void Managed::OnSomeEvent(void) 
{ 
    OnChange(); 
} 

注意备用bind<R>()形式这是用过的。

+0

我想在这里做类似的事情。任何关于将字符串传入/传出回调的建议? http://stackoverflow.com/q/42304020/15369 – 2017-02-19 22:42:19

4

google搜索一些后,我终于找到了nice blog post有关如何做到这一点。该帖子中的代码比我需要的要多一点,但主要的核心是使用全局免费函数,该函数接受一个包含在gcroot中的托管指针的参数。在下面的代码中查看SomeEventProxy(...)的示例。然后该函数转过来并调用我试图绑定的托管成员。我的解决方案出现在下面供将来参考

#include <msclr/marshal.h> 

#include <boost/bind.hpp> 
#include <boost/signal.hpp> 
#include <iostream> 

#using <mscorlib.dll> 

using namespace System; 
using namespace msclr::interop; 

typedef boost::signal<void (void)> ChangedSignal; 
typedef boost::signal<void (void)>::slot_function_type ChangedSignalCB; 
typedef boost::signals::connection Callback; 


class Native 
{ 
public: 

    void ChangeIt() 
    { 
     changed(); 
    } 

    Callback RegisterCallback(ChangedSignalCB Subscriber) 
    { 
     return changed.connect(Subscriber); 
    } 

    void UnregisterCallback(Callback CB) 
    { 
     changed.disconnect(CB); 
    } 

private: 
    ChangedSignal changed; 
}; 



delegate void ChangeHandler(void); 


public ref class Managed 
{ 
public: 
    Managed(Native* Nat); 
    ~Managed(); 
    void OnSomeEvent(void); 

    event ChangeHandler^ OnChange; 

private: 
    Native* native; 
    Callback* callback; 
}; 


void SomeEventProxy(gcroot<Managed^> This) 
{ 
    This->OnSomeEvent(); 
} 


Managed::Managed(Native* Nat) 
: native(Nat) 
{ 
    native = Nat; 
    callback = new Callback; 
    *callback = native->RegisterCallback(boost::bind(SomeEventProxy, gcroot<Managed^>(this))); 
} 

Managed::~Managed() 
{ 
    native->UnregisterCallback(*callback); 
    delete callback; 
} 

void Managed::OnSomeEvent(void) 
{ 
    OnChange(); 
} 


void OnChanged(void) 
{ 
    Console::WriteLine("Got it!"); 
} 

int main(array<System::String ^> ^args) 
{ 
    Native* native = new Native; 
    Managed^ managed = gcnew Managed(native); 

    managed->OnChange += gcnew ChangeHandler(OnChanged); 

    native->ChangeIt(); 

    delete native; 
    return 0; 
} 
相关问题