11

私はネイティブ C++ クラスで boost::signal を使用しています。現在、ネイティブ C++ コールバックを .NET イベントとして公開できるように、C++/CLI で .NET ラッパーを作成しています。マネージ クラスのメンバー関数のアドレスを取得するために boost::bind を使用しようとすると、コンパイラ エラー 3374 が発生し、デリゲート インスタンスを作成しない限り、メンバー関数のアドレスを取得できないというメッセージが表示されます。boost::bind を使用してマネージド クラスのメンバー関数をバインドする方法を知っている人はいますか?

明確にするために、次のサンプル コードではコンパイラ エラー 3374 が発生します。

#include <boost/bind.hpp>

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

    void OnSomeEvent(void)
    {
    }
};
4

2 に答える 2

4

さらにグーグルで調べた後、最終的にこれを行う方法についての素晴らしいブログ投稿を見つけました。その投稿のコードは必要以上のものでしたが、主なポイントは、gcroot<> テンプレートにラップされた管理対象の this ポインターの引数を取るグローバル フリー関数を使用することでした。例については、以下のコードの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;
}
于 2008-10-03T01:44:09.843 に答える