Boost를 사용하는 방법 :: C ++/CLI에서 바인딩하여 관리 클래스의 구성원을 바인드

StackOverflow https://stackoverflow.com/questions/163757

문제

기본 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;
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top