كيفية استخدام دفعة :: ربط في C ++ / CLI لربط عضوا في الفئة المدارة

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

سؤال

وأستخدمه دفعة :: إشارة في فئة الأم C ++، وأنا الآن وأنا أكتب مجمع. NET في C ++ / CLI، حتى أستطيع أن فضح الأصلي C ++ الاسترجاعات عن الأحداث. NET. عندما أحاول استخدام دفعة :: ربط لاتخاذ عنوان دالة عضو من الفئة المدارة بلدي، وأحصل على خطأ مترجم 3374، قائلا لا أستطيع تحمل عنوان دالة عضو إلا إذا أنا خلق مثيل مندوب. لا أحد يعرف كيفية ربط دالة عضو من فئة إدارتها باستخدام دفعة :: مأزق؟

لتوضيح، يؤدي نموذج التعليمات البرمجية التالية مترجم خطأ 3374:

#include <boost/bind.hpp>

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

    void OnSomeEvent(void)
    {
    }
};
هل كانت مفيدة؟

المحلول

وبينما تعمل إجابتك، وإنما يعرض بعض من التطبيق الخاص بك إلى العالم (مدار :: OnSomeEvent). إذا كنت لا تريد أن يكون الناس قادرين على رفع الحدث عند_التغيير طوعا أو كرها من خلال التذرع OnSomeEvent ()، يمكنك تحديث صفك إدارتها على النحو التالي (على أساس <لأ href = "http://msdn.microsoft.com/ أون لنا / المكتبة / 367eeye0 (VS.80) .ASPX "يختلط =" noreferrer "> هذه النصيحة ):

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>() البديل الذي يتم استخدامه.

نصائح أخرى

وبعد غوغلينغ بعض أكثر، وأخيرا وجدت <لأ href = "http://mr-sharpoblunto.junkship.org/2007/11/mapping-boostsignals-to-net-events.html" يختلط = "noreferrer نوفولو "> بلوق وظيفة لطيفة حول كيفية القيام بذلك. كان رمز في هذا المنصب أكثر من ذلك بقليل مما كنت في حاجة، ولكن كانت الكتلة الرئيسية لاستخدام وظيفة الحرة العالمية التي تأخذ حجة تمكن هذا المؤشر ملفوفة في قالب 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