Boost를 사용하는 방법 :: C ++/CLI에서 바인딩하여 관리 클래스의 구성원을 바인드
-
03-07-2019 - |
문제
기본 C ++ 클래스에서 Boost :: 신호를 사용하고 있으며 이제 C ++/CLI에서 .NET 래퍼를 작성하여 기본 C ++ 콜백을 .NET 이벤트로 노출시킬 수 있습니다. 부스트 :: 관리 클래스의 멤버 함수의 주소를 취하기 위해 바인드를 사용하려고 할 때, 컴파일러 오류 3374를 얻습니다. boost :: bind를 사용하여 관리 클래스의 멤버 함수를 바인딩하는 방법을 아는 사람이 있습니까?
설명을 위해 다음 샘플 코드는 컴파일러 오류 3374를 유발합니다.
#include <boost/bind.hpp>
public ref class Managed
{
public:
Managed()
{
boost::bind(&Managed::OnSomeEvent, this);
}
void OnSomeEvent(void)
{
}
};
해결책
답변이 작동하는 동안 일부 구현을 세계에 노출시킵니다 (Managed :: onsomeevent). 사람들이 onsomeevent ()를 호출하여 Onchange 이벤트 Willy-Nilly를 올릴 수 있기를 원하지 않으면 다음과 같이 관리 된 클래스를 업데이트 할 수 있습니다 ( 이 조언):
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>()
사용되는 형태.
다른 팁
더 인터넷 검색을 한 후 마침내 a를 찾았습니다 멋진 블로그 게시물 이 작업을 수행하는 방법에 대해. 그 게시물의 코드는 내가 필요로하는 것보다 조금 더 많았지 만 메인 너겟은 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;
}
제휴하지 않습니다 StackOverflow