シグナル、というと、Linuxのsignalを考えてしまうかもしれない。
しかしQtのシグナルは別のものである。
そして、Qtのシグナルは重要というか何というか、基本をなすしくみなのでちゃんと理解しておきたい。
http://labs.qt.nokia.co.jp/2010/06/17/signals-and-slots.html
GUIのウィジェットに関して言えば、シグナルは「イベント」みたいなものだ。
ボタンをクリックした、とか、テキストが変更された、とか。
自分でボタンを作ると考えた場合、クリックはこんな感じで対処しそうだ。
- ボタンはclassにする
- 汎用的にしたいので、クリックしたときに呼び出される処理をコンストラクタなどでコールバック登録する
- 専用のボタンなら、派生クラスを作ってクリックイベントは自分で実装
しかし、コールバック登録するということは、その関数がstaticになってないといかん。
いかんことはないだろうけど、メンバ関数をコールバック登録する方法がよくわからんので、やりたくない。
- Qtの場合、イベントが発生するときに「シグナルを送信」する。
- 送信されたシグナルは、「接続されたスロット」に通知される。
- シグナルとスロットの接続は動的に行い、メンバ関数(スロット)を指定する。
delegateみたいな感じだろうか。
シグナルの送信は、簡単だ。
メンバ関数定義はpublicとかprivateではなく「signals」に置く。
送信時は、キーワードemitを付けて呼び出すだけ。関数本体は書かない。
受けとるスロットも、似たようなものだ。
メンバ関数定義は「slots」に置く。これはpublic slotsやprivate slotsにできる。
シグナルとスロットの接続は、QObject::connect()を使う。
なんで関数本体がないシグナル定義が呼び出せるかというと、moc、というコンパイラが別にあるからだ。
メタオブジェクトコンパイラ、の略らしい。
「メタオブジェクト」というものがよくわからないが、Qt用のclass定義を読み込んでcppソースをつくるのだ。
その中で、シグナル関数も生成されている。
これは一例。
// SIGNAL 0
void Employee::salaryChanged(int _t1)
{
void *_a[] = { 0, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
QMetaObject::activate(this, &staticMetaObject, 0, _a);
}
mocが作るcppには、これ以外にもいろいろと生成している。
どうやってQt用のclass定義を見分けているかというと、おそらくQ_OBJECTマクロだ。
「Qt用のclass定義先頭に"Q_OBJECT"と書け」というルールなのだ。
mocがこそっとstaticメンバ関数を生成しているので、おそらくこんな流れになっているんじゃなかろうか。
- 「イベント送信」により、QMetaObject::activate()が呼ばれる
- activate()の引数で渡されたstaticMetaObjectには、mocが生成したstaticメンバ関数が書かれているので、それを呼び出す。
- staticメンバ関数内でうまいことやって、接続されたスロットを呼び出す。
staticメンバ関数を見ると、引数によって呼び先がシグナルかスロットかに分岐している。
シグナルを呼べるようになっているのは、シグナルとシグナルを接続できるようになっているからだろうか。
引数確認のためにstrcmp()で文字列化された接続先スロットを確認するなど、そこそこ軽くはない処理になっている。
オーバーヘッドをなくしたい場合は、プロファイラで比重が重たいところを探して、そこが安全であればチェックをコメントアウトしていく、というようなことをやっていかないかんのかもしれない。
こんな感じで、これからしばらくQtをやっていく。
目標は、こんな感じの会話ができること、だ。
依頼人:「○○なアプリを作ってください」
私:「・・・Qtで・・・作ることになるが」
依頼人:「もちろん構いません」
私:「報酬はスイス銀行に振り込んでくれ・・・」
いや、スイス銀行はどうでもいいのだ。口座持ってないし。
今の私は、アプリを作るプラットフォームを持っていない。
Androidで作ることもあるし、VC#で作ることもある。
でも、AndroidはJavaで苦手だし、VC#はWindows限定に近くなってしまう。
作って組込みアプリにするとなると、C/C++が望ましい。
0 件のコメント:
コメントを投稿
コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。
注: コメントを投稿できるのは、このブログのメンバーだけです。