問題タブ [boost-signals2]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c++ - `boost::signals2` のシグナル シグネチャはどのように実装されていますか?
私は自分のプロジェクトでしばらく使用boost::signals2
しています。残念なことに、それらが内部でどのように実装されているかはまだわかりません。私の問題は、信号の定義そのものからすでに始まっています。のような定義はどのように
扱い?実装の詳細から、署名が適切な名前のテンプレート パラメーターになることがわかりますSignature
。ただし、構文がわかりません。この構文は C++ 標準で許可されていますか? シグナルがこの形式で提供されている場合、シグナルは関数シグネチャをどのように「保存」できますか?
すでにソースを調べてみましたが、この構文の説明を見つけることができませんでした。どんな助けでも大歓迎です。
c++ - Objective-C/C++ で Signals2 を使用して C++ モデルをコントローラーに接続する
私は、ほぼ 1,000 の異なる種類のデータ項目 (ただし、100 未満の異なるデータ構造/クラス) を持つクロスプラットフォームの C++ データ モデルを開発しています。モデルからコントローラーへのメッセージ (つまり、一部のデータ項目が変更されたというコントローラーへの通知) を処理するために、boost:signals2 を使用することを考えています。これは、異なる OS プラットフォーム間で同じままである統一されたオブザーバー パターンを作成するのに役立つと思います。最初の実装は Mac OS / IOS で行われ、その後の UI は .net と unix で開発されました。
質問:
1) データモデルの観測を設定するには、コントローラーはどのタイプのオブジェクトをシグナル2オブジェクト/スロットに接続する必要がありますか? 観察される各データ項目のコントローラーに特定の関数/メソッド/セレクターが必要ですか? これらの関数は、C、C++、または Objective-C/C++ 関数である必要がありますか?
2) シグナルはどのレベルの粒度を持つべきですか? データの各項目は独自のものを持つべきですか? それとも、関連する構造/レコードのモデルの管理は、構造/レコードのタイプごとに単一のシグナルを維持する必要がありますか? たとえば、どのデータ項目が変更されたかについての情報を渡すために、アプリケーションの設定はすべての設定データに対して 1 つのシグナルを持つべきでしょうか?
3) シグナルを送信するプロセス (またはシグナルを受信するスロット) は、SEPARATE THREAD で実行する必要がありますか?
4) Cocoa には Key-Value Observing 用の独自のシステムがあることを理解しています。しかし、そのようなシステムは、モデルのシグナル 2 ベースのオブザーバー パラダイムと組み合わせるのに有利でしょうか? それとも単に冗長なのでしょうか?
アップデート:
実際の signal2 オブジェクト (オブザーバーではない) の「粒度」に関しては、ドキュメントごとに 1 つ、アプリケーション設定用に 1 つ持つことから始めるのが良いと思います。私のドキュメント データには既に「キー」の概念があるため、UI コンポーネントがモデル データの特定の項目に関連付けられている一般的な UI ケースを一般化できる可能性があります。
c++ - boost::signals::trackable から派生する頻度は?
boost::signals::trackable
Boost.Signals を使用する場合、オブジェクト/接続の有効期間の管理を容易にするために、boost から派生させることができます( boost のドキュメントを参照してください)。
私はプロジェクトの初期段階にあり、から派生するかどうかを考えていboost::signals::trackable
ます
- 将来 Boost.Signals を使用する可能性がある、私が作成するすべての新しいクラス
trackable
またはクラスでのみ、基本クラスの機能が必要になると確信しています
最初のアプローチの主な理由は、 からの導出を忘れないようにするためですboost::signals::trackable
。
また、次のような二重導出
不要になる。
一方で、メモリ リークを防止することは設計上の主要な側面であってはなりません。valgrind などのテストおよびプロファイリング ツールを使用して、メモリ リークを検出する必要があります。
成長するプロジェクトに適しているアプローチはどれですか?
c++ - C++ シグナル 2 スロット コールバックには、Objective-C/C++ クラス/セレクター (メソッド) 情報を含めることができますか?
これはあなたの何人かにとって非常に明白であるに違いありませんが、私はこの例を見つけることができません:
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 つのパラメーターを信号からスロットに送信したいと思うでしょう。
誰か闇に光を当ててくれませんか?
c++ - boost::signals2 と例外処理
boost::signals2 でスロットが呼び出された特定の瞬間をオーバーライドし、いくつかのアクション (ロギング、デバッグ、例外処理) を実行する方法はありますか?
シグナル/スロットは、コード内の実行パスがさまざまなソフトウェアコンポーネント間で交差する場所であり、各コンポーネントはオプションであることが意図されているため、動作がおかしい場合は実行時に無効にできるため、スロット呼び出しの瞬間に例外をキャッチしたいと思います。そのため、スロット呼び出しがスローされたとき (外部ライブラリから来る可能性があり、単に std::bad_alloc である可能性があります)、それについて通知され、どのコンポーネントにシグナルが送られたかを知りたいので、そのコンポーネントを強制終了できます。
そこのスロットまたは接続オブジェクトにアクセスできないため、コンバイナーでそれを行う方法がわかりませんか? そのため、情報を取得する方法がわかりません。(すべてのスロットで戻り値の型を変更することは不可能です。)
私が見逃したこれを行うための非常に簡単な方法はありますか?
そうでない場合、どうすればいいですか?
slot_call_iterator (try/catch で呼び出しをラップするため) や connection_body_base (たとえば、それが属するコンポーネントに関する情報を格納するため) などをサブクラス化し、boost でこれらを使用しますか? (どのように?)
または、signals2::slot<...> をサブクラス化し、コンストラクターで所有コンポーネントに関する情報を提供し、何らかの方法で operator()(...) をオーバーロードしますか? (それについてもわかりませんが、すべてのテンプレートマジックでは難しいようです。)
c++ - boost::signals2 ライブラリをリンクするときの undefined-reference
2 つのライブラリを自分のプログラムにリンクしたいと考えています。最初のものは、シグナルを発する(クラスProducerObjectの) オブジェクトを定義します。2 番目のライブラリは 2 つのクラスを定義します。1 つはProducerObjectの複数のインスタンスを含むスレーブ クラス、もう 1 つはスレーブ クラスを介してProducerObjectのシグナルをサブスクライブできるマスター クラスです。
最初のライブラリのコードは次のとおりです。
ProducerObject.hpp:
ProducerObject.cpp:
次のコマンドを使用して、コードと同じレベルにある Debug ディレクトリでこれをコンパイルします。
g++ -O0 -g3 -Wall -c -fmessage-length=0 -fPIC -MMD -MP -MF"ProducerObject.d" -MT"ProducerObject.d" -o "ProducerObject.o" "../ProducerObject.cpp"
g++ -shared -o "libProducerObject.so" ./ProducerObject.o
2 番目のライブラリのコードは次のとおりです
。MasterAPI.hpp:
SlaveAPI.hpp:
SlaveBase.hpp:
MasterAPI.cpp:
SlaveAPI.cpp:
SlaveBase.cpp:
このコードを次のようにコンパイルします。
g++ -I"/home/chris/workspace/ProducerObject" -O0 -g3 -Wall -c -fmessage-length=0 -std=c++0x -fPIC -MMD -MP -MF"MasterAPI.d" -MT"MasterAPI.d" -o "MasterAPI.o" "../MasterAPI.cpp"
g++ -I"/home/chris/workspace/ProducerObject" -O0 -g3 -Wall -c -fmessage-length=0 -std=c++0x -fPIC -MMD -MP -MF"SlaveAPI.d" -MT"SlaveAPI.d" -o "SlaveAPI.o" "../SlaveAPI.cpp"
g++ -I"/home/chris/workspace/ProducerObject" -O0 -g3 -Wall -c -fmessage-length=0 -std=c++0x -fPIC -MMD -MP -MF"SlaveBase.d" -MT"SlaveBase.d" -o "SlaveBase.o" "../SlaveBase.cpp"
g++ -L"/home/chris/workspace/ProducerObject/Debug" -shared -o "libObjectAPI.so" ./MasterAPI.o ./SlaveAPI.o ./SlaveBase.o -lProducerObject
最後に、プログラム自体:
ObjectTest.cpp:
コンパイル:
g++ -I"/home/chris/workspace/ProducerObject" -I"/home/chris/workspace/ObjectAPI" -O0 -g3 -Wall -c -fmessage-length=0 -std=c++0x -MMD -MP -MF"ObjectTest.d" -MT"ObjectTest.d" -o "ObjectTest.o" "../ObjectTest.cpp"
g++ -L"/home/chris/workspace/ProducerObject/Debug" -L"/home/chris/workspace/ObjectAPI/Debug" -o "ObjectTest" ./ObjectTest.o -lObjectAPI -lProducerObject
このプログラムは次の出力を生成します。これはまさに必要なものです。
--> 専用メッセージを master1 に送信:
MasterAPI(1) で受信したメッセージ: 値 = 11--> procuder1 からのブロードキャスト メッセージの送信:
MasterAPI(1) で
受信したメッセージ: 値 = 22 MasterAPI(2) で受信したメッセージ: 値 = 22--> procuder2 からのブロードキャスト メッセージの送信:
MasterAPI(1) で受信したメッセージ: 値 = 33
この出力を生成するには、引数としてboost::functionを取る補助メソッドconnect2に依存する必要がありました。スロットの署名は既に *broadcast_slot_t* タイプに含まれている必要があるため、これは避けたいと思います。したがって、達成したいコードのバージョンにはconnect2メソッドが含まれていません。しかし、メソッドMasterAPI::subscribeToProducerの実装でconnect2からconnectに切り替えると (コメントを test に変更するだけです)、最後のコンパイル フェーズ (すべてがリンクされている場所) で次のエラーが発生します。
なぜ、どのように回避するのですか?
c++ - boost::signals2 のバインディング クラス メンバー関数
std::bind を使用して、クラス メンバー関数を含むラムダを作成しましたが、boost::signals2 はそれを受け入れません。
を呼び出してCut
、新しいものがある場合に通知したいクラスがあります。Event
void Cut::newEvent(Event& e)
Cut のインスタンスへのラムダ バインディングを作成しましたが、Event を渡すと期待どおりに動作します。(コードはコンパイルされ、出力は「Registered new event」です。)
ただし、このラムダをインスタンスに接続しようとするboost::signals2::signal<void(Event&)>
と、次のメッセージが表示されます。
error: 'f' cannot be used as a function
main() の関数として使用できるため、これは奇妙です。std::function<void(Event&)>
( auto の代わりに使用しても同じ結果が得られます。
これを機能させることは可能ですか?現在機能していないのはなぜですか?
これは関連するコードです:
boost - boost::signals2::signal でコピー不可オブジェクトをスロットとして使用する方法
ブースト信号で使用したいコピー不可能なオブジェクトのインスタンスがあります2。connect メソッドは、ファンクタがコピー可能であることを期待しています。これを回避する方法はありますか?以下のコードのコメントを削除するにはどうすればよいですか?
no_copy
オブジェクトへの参照をメソッドに渡す方法はありconnect
ますか?
c++ - テンプレートでの Signals2 connect() の使用
さまざまなタイプのデータを送信するために必要ないくつかの反復機能のテンプレート クラスを作成しようとしています。ただし、私の問題 (私が思う) は、実際にはboost::signals2::signal::connect()を利用しているInterfacePublisher::addSubscription()関数にあります。
派生クラスがそれらをオーバーライドしていても、接続関数が基本クラスの場所を取得しているようです。これには修正が加えられると確信していますが、今は長い間それで立ち往生しています。
以下にコードを貼り付けます。アイデアは、テンプレートを介してクラス名をハードコーディングせずにStringPublisherからStringSubscriberに文字列を渡すことです。