web-dev-qa-db-ja.com

Qtの特定のスロットに接続されている信号を特定します

Qtアプリケーションに自分自身を注入し、特定のスロットが接続されている信号を把握しようとしていますが、これを行うための情報が見つかりません。箱から出してこれを行うためのメカニズムはありますか?もしそうなら、これはQtScriptに公開されていますか? (そうでない場合は、簡単にラップできます。)

そのようなメカニズムがない場合、それを追加するための最良の方法は何でしょうか?単純なフック以外で既存のアプリケーションを操作することはできませんが、QObject :: connectをフックして接続を自分で保存することはできますが、それが最善の方法かどうかはわかりません。

27
Cody Brocious

Qtコードベースとドキュメントを掘り下げた後(ここや他の場所から多くの役立つヒントを得ました)、QObject :: connect(静的オーバーロード)をフックすることに決めました。どうして?他のソリューションでは、どのオブジェクトがシグナルを提供しているかを知る必要があります。プライベートフィールドを掘り下げるか、Qtのデバッグビルドが必要です。結局、QObject :: connectをフックすると、アプリケーションで接続されているすべてのものが得られ、スロットに簡単にマップして戻すことができます。

3
Cody Brocious

Qtは、特定の信号が接続されているスロットを格納していると思います。そのため、Qtを送信すると、すべてのレシーバーが呼び出されます。したがって、レシーバーのリストにアクセスできます。

デバッグの目的で、次のものがあります。

void QObject :: dumpObjectInfo()

このオブジェクトの信号接続などに関する情報をデバッグ出力にダンプします。

この関数はデバッグに役立ちますが、ライブラリがリリースモードでコンパイルされている場合(つまり、デバッグ情報がない場合)は何もしません。

そして、信号が接続されているスロットのリスト:

int QObject ::レシーバー(const char * signal)const [protected]

信号に接続されているレシーバーの数を返します。

MetaObject()は、スロットのQMetaMethodを提供しますが、その接続に関する情報はありません。

ただし、オブジェクトがわかっている場合は、すべてのシグナルを調べ(メタオブジェクトを使用して、シグナルのメソッドタイプをテストします)、receivers()が提供するスロットを使用して逆インデックスを作成できます。

29
duncan

Qtの内部ミューテックス/セマフォを保持せずに信号スロット接続のリストを安全に反復する方法はありません。信号とスロットはいつでも出入りできるので、せいぜい正しいとは限らないリストを取得することになります-したがって役に立たないでしょう。

QObject::connectで行うフックは、それ自体では不十分です。このようなフックから取得するデータには、次のような問題があります。

  1. オブジェクトにアクセスしようとするまでにすでに削除されているオブジェクトへのポインタがある場合があります。 QPointerを使用してこれを軽減できますが、これは、コードを実行するスレッドに存在するオブジェクトに対してのみ機能します。オブジェクトリストを収集するには、オブジェクトを他のスレッドに挿入する必要があります。

  2. あなたはもう存在しない接続を持っているかもしれません。オブジェクトが存在しなくなると接続が削除されるため、QObject::disconnectをフックするだけでも不十分です。

あなたが直面している問題は非常に複雑であり、堅牢なソリューションは単に「フック」QObject::connectに限定されるものではありません。

残念ながら、あなたは言っていませんなぜスロットに接続する信号のリストが必要です。それの目的は何ですか?

9
Kuba Ober