まえがき
開発でQtを使用したすべての人が、メタ情報がどのように配置され、この美しいフレームワーク内で何が起こっているのかを知りたいと思いますか? これがこのレコードの目的です。ソースを調べて、動的メタオブジェクトの実装を記述しようとします(ただし、このレコードには含まれません)。 シグナルとスロットをリアルタイムで作成できるメタオブジェクト。
多くの人は、
すべてがすでに実装されていると言い
ます (利用
できない場合:
Googleのキャッシュにあります )。 しかし、そのような実装では、
QObject::connect
作成できません。 そのような実装の値はゼロになる傾向があります。
少し勉強
したがって、
QObject
、
QObject
クラスのコンテンツを見てみましょう。 なんで? すべてのメタ情報クラスは
QObject
子孫でなければならず、mocがメタ情報を生成する
Q_OBJECT
マクロも持っている必要があります。
公式サイトからQtからコードをコピーします。 Qt 5.4を使用します。
したがって、クラス宣言自体は次のようになります。
QObjectクラスコード class Q_CORE_EXPORT QObjectData { public: virtual ~QObjectData() = 0; QObject *q_ptr; QObject *parent; QObjectList children; uint isWidget : 1; uint blockSig : 1; uint wasDeleted : 1; uint isDeletingChildren : 1; uint sendChildEvents : 1; uint receiveChildEvents : 1; uint isWindow : 1;
同時に、単純なクラスAでプロジェクトを作成できます
#include <QObject> class A : public QObject { Q_OBJECT public: explicit A(QObject *parent = 0); ~A(); signals: void signal(); public slots: void slot(){} };
しかし、これらすべての中で、メタオブジェクト自体とその構成要素に注意を払う必要があります。
したがって、これまで見てきたことから、いくつかの結論を導き出すことができます。動的メタ
QDynamicMetaObjectData * QObjectData::metaObject
動作時間
QDynamicMetaObjectData * QObjectData::metaObject
と
QMetaObject * QObjectData::dynamicMetaObject() const
関数です。 したがって、Qtをどのように使用するのか、Qtをどのように使用するのかを学ぶ必要があります。
退屈なソースの読み取りをスキップして、すぐに言います。動的なメタオブジェクトを作成するためのクラスも残しました。
だから私たちから出てくるもの。 新しいメタオブジェクトを作成し、
QObject
子孫にある
QObject
しかし、あなたはあなたの信号とスロットのために場所を取ることができます。 一般的に、私たちの病気の想像力をサポートするすべてを行うために、私は信号とスロットの両方を追加できるメタオブジェクトの作成にもっと触発されたので、ここでそのようなメタオブジェクトを作成するための準備を強調します。
私たちは怠withと戦い、タスクに関する情報を収集します
したがって、メタオブジェクトを作成するには、メタオブジェクトの一般的な配置を確認する必要があります。 これを行うために、ソースに再び登り、これを見つけます:
メタオブジェクト構造 struct Q_CORE_EXPORT QMetaObject {
ここから、およびMOCジェネレーターを使用したリストから、有効なメタオブジェクトには、
stringdata
と
data
2つの変数のみを
data
するか、
QMetaObject
クラスのすべての関数を完全に書き換える必要があることは明らかです。 2つの悪のうち、私はより少ないものを選択しました-このデータの検索はQtによって実行され、通常のメタオブジェクトより遅く見えないため、このデータを記入することにしました(はい、これは時期尚早の最適化です)。
始めるために、最も簡単なもの-文字列情報を見てみましょう。 MOCは、テストクラスAにこのコードを提供します。
文字列配列 struct qt_meta_stringdata_A_t { QByteArrayData data[4]; char stringdata[15]; }; #define QT_MOC_LITERAL(idx, ofs, len) \ Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \ qptrdiff(offsetof(qt_meta_stringdata_A_t, stringdata) + ofs \ - idx * sizeof(QByteArrayData)) \ ) static const qt_meta_stringdata_A_t qt_meta_stringdata_A = { { QT_MOC_LITERAL(0, 0, 1),
つまり 相対文字列参照を含む
QByteArrayData
配列のみがあります(
QByteArrayData
自体に対して)。 したがって、MOCのように、一緒にではなく、各行をメモリに簡単に個別に配置できます。
ここで、メインのメタ情報に移りましょう。ここでは、MOCが大きなuint配列を用意しました。
大きなuint配列 static const uint qt_meta_data_A[] = {
3つのブロックに分割します。 最初のブロックは、通常の
QMetaObjectPrivate
クラスです。
QMetaObjectPrivateコア struct QMetaObjectPrivate { enum { OutputRevision = 7 };
最初のブロックに等しい対応は難しくありません。 2番目のブロックはもう少し複雑です。 そこで構造の配列を取得します(Qtでは、そのような構造は記述されていません。これは非常に奇妙なので、独自の
DataMethodInfo
)。
DataMethodInfo struct DataMethodInfo{ uint name;
これですべてが明確になりました。 しかし、引数の説明ははるかに楽しいです。 最初にメソッドが返す型があり、ほとんどの場合
QMetaType::Void
が発生します。 以下は、すべてのタイプの引数のリストです。 つまり、
QString testString (QString src, QString dst)
メソッド
QString testString (QString src, QString dst)
場合、2 QMetaType :: QStringが存在します。 メソッドに引数がない場合、何も入力されません。 そして、引数のタイプをリストした後、これらの引数の名前のリストがあります。 したがって、
QString testString( QString src, QString dst )
メソッド
QString testString( QString src, QString dst )
、メタデータコードは次のようになります。
static const qt_meta_stringdata_A_t qt_meta_stringdata_A = { { QT_MOC_LITERAL(0, 0, 1),
引数のオフセットを計算するのは間違っているかもしれませんが、その意味は明らかだと思いますか? MOCの代わりにこのコードを挿入すると、クラスAメタオブジェクトにtestStringメソッドを追加できますが、機能しませんが、リストに表示されます。 そして、独自の一意のIDを持ちます。
データの一部からこれらすべてを生成するコードを記述するだけです。 興味がある場合は、次の号で、完全に機能する動的なメタオブジェクトを記述する方法を示します。