1

これはあなたの何人かにとって非常に明白であるに違いありませんが、私はこの例を見つけることができません:

C++ クラス メンバー関数またはファンクターであるスロット コールバックを接続するには、boost::signals2 シグナルが必要です。これにより、モデル コールバックを Objective-C/C++ コントローラー コードに作成できます。

そのコールバックは、C++ コールバック関数内で呼び出すことができる Objective-C/C++ メソッドのインスタンスのクラスとセレクターを格納する必要があります。(Objective-C/C++ メソッドの直接コールバック関数アドレスを実際に提供する方法はないと仮定しています)。Objective-C/C++ メソッドを呼び出すための情報を保持するために、C++ クラス/ファンクターのインスタンスを作成する必要があると想定しました。

また、Class と SEL (セレクター) を分離して、void* として渡すことなく、コールバック用の C++ クラスのインスタンス内に格納できるかどうかもわかりません。C++ コールバックが signal() によって呼び出されると、class_getInstanceMethod と method_getImplementation を使用して、それらを使用可能な (呼び出し可能な) 形式に変換できると期待しています。

さらに、信号の性質に関する情報を提供できる任意の構造体 ("EventInfo") を持つ少なくとも 1 つのパラメーターを信号からスロットに送信したいと思うでしょう。

誰か闇に光を当ててくれませんか?

4

2 に答える 2

1

長い時間がかかりましたが、ついにこれを理解しました。これを行う簡単な方法があるかもしれませんが、boost::signals2 シグナルと Objective-C コールバック関数の間のブリッジとして機能する C++ クラスを .mm ファイルに作成する必要があることがわかりました。

CPPToCocoaModelMessageCallbacks.h 内:

/* ------------------------------------------------------------------------
    class CPPToCocoaModelMessageCallback - 
--------------------------------------------------------------------------- */
class CPPToCocoaModelMessageCallback
{
public:
    CPPToCocoaModelMessageCallback( PMD_Signal_Messenger<PrefEvent> *theSignalClass, 
                                    int         whichPrefIdxToObserve, 
                                    id          pObjCClass, 
                                    SEL         pObjCMethod);

    ~CPPToCocoaModelMessageCallback();

    void    CallBackMessage(PrefEvent* pPrefEvent);


private:

    id          fpObjCClass;
    SEL         fpObjCMethod;

    ls_index    fWhichPrefIdxToObserve;

    boost::signals2::connection fTheConnection;

};  // CPPToCocoaModelMessageCallback

CPPToCocoaModelMessageCallbacks.mm 内

/* ------------------------------------------------------------------------
    CPPToCocoaModelMessageCallback - CONSTRUCTOR

    whichPrefIdxToObserve - the preference idx to observe

    Pass the id and selector of the Objective-C/C++ object & method to be
    called.
--------------------------------------------------------------------------- */
CPPToCocoaModelMessageCallback::CPPToCocoaModelMessageCallback(PMD_Signal_Messenger<PrefEvent> *theSignalClass, int whichPrefIdxToObserve, id pObjCClass, SEL pObjCMethod) 
        :   fpObjCClass (pObjCClass),
            fpObjCMethod (pObjCMethod),
            fWhichPrefIdxToObserve (whichPrefIdxToObserve)
{
    fTheConnection = theSignalClass->ObserveSignal(&CPPToCocoaModelMessageCallback::CallBackMessage, this);
}

/* ------------------------------------------------------------------------
    ~CPPToCocoaModelMessageCallback - DESTRUCTOR

    Pass the id and selector of the Objective-C/C++ object & method to be
    called.
--------------------------------------------------------------------------- */
CPPToCocoaModelMessageCallback::~CPPToCocoaModelMessageCallback()
{
    fTheConnection.disconnect();
}


/* ------------------------------------------------------------------------
    CPPToCocoaModelMessageCallback::CallBackMessage - 

    Handles single and range-type preference change events.
--------------------------------------------------------------------------- */
void CPPToCocoaModelMessageCallback::CallBackMessage(PrefEvent* pPrefEvent)
{
    // Only make the callback if this event is the preference we're observing

    if (pPrefEvent->GetChangedPrefIdx() == fWhichPrefIdxToObserve) {
        [fpObjCClass performSelector:fpObjCMethod];
    }
}

/////////////////////////////////////////////// ////////////////////////////

あなたのcontroller.mmで:

// set up messaging from Model.  The message callback functions must be destructed in dealloc.  
// I've done this in awakeFromNib but it could be elsewhere

- (void)awakeFromNib {

    PMD_Signal_Messenger<MyEventKind>* theModelClass = GetMyModelClassPointer();

    displayMenuPrefChangedCallBack = new CPPToCocoaModelMessageCallback(theModelClass, kAppPrefDictionaryDisplayShortDef, self, @selector(displayMenuChanged));
}


/* ------------------------------------------------------------------------
    displayMenuChanged - this gets called when the model fires a signal
        (via CPPToCocoaModelMessageCallback::CallBackMessage())

--------------------------------------------------------------------------- */
- (void) displayMenuChanged
{
    NSLog(@"displayMenuChanged\n");

    // DO SOMETHING TO RESPOND TO THE SIGNAL (in this case I'm reloading an NSWebView):

    [self reloadWebViewText];
}

/////////////////////////////////////////////// ////////////////////////////

シグナリング オブザーバーのモデル クラスと結合するクラス:

PMD_Signal_Messenger.h:

/* ------------------------------------------------------------------------
    class PMD_Signal_Messenger<MyEventKind> -

        This class is designed to be multiple inherited with various
        Model classes.
--------------------------------------------------------------------------- */
template <class MyEventKind>
class PMD_Signal_Messenger {
public:

    PMD_Signal_Messenger() { }
    ~PMD_Signal_Messenger() { }

        template<typename Fn, typename Obj>
            boost::signals2::connection ObserveSignal(Fn callback, Obj &object) {
                return fSignalObservers.connect(boost::bind(callback, object, _1));
            }

protected:
    boost::signals2::signal<void (MyEventKind*)> fSignalObservers;  // all observers of my preference changes

private:
    PMD_Signal_Messenger(const PMD_Signal_Messenger& thePMD_Signal_Messenger)   { assert(false); }  // prevent copy constructor
};

モデルの変更を通知する .cpp MODEL ファイル内:

// construct theEvent (your own struct) and fire the signal with your event structure that gets passed to CPPToCocoaModelMessageCallback::CallBackMessage()

MyEventKind theEvent(someUsefulParams);

fSignalObservers(&theEvent);
于 2013-06-14T22:19:30.343 に答える