5

問題

Q_OBJECTとQ_PROPERTYを使用して、スクリプトからいくつかのオブジェクトにアクセスするプロジェクトを作成しています。私には2つの問題があります:

  1. 前方宣言を使用するクラスをスクリプト可能にする
  2. プロパティをポインタとして返す

説明

1.なぜ前方宣言?

Aはテンプレートのためにヘッダーに完全なBタイプを必要とするため、クラスBはAへの前方宣言を取得します。Bはヘッダーに不完全な型(A *)のみを必要とするため、前方宣言は有効です。

2.なぜポインタを返すのですか?

スクリプト内の実際のオブジェクトにアクセスする必要があるため、コピーを返すことはできません。Qtはスロットが参照を返すことを許可しないため、参照を返すことはできません。それらのタイプは無視され、void*のみを返します。

コード

ペーストビンまたはZIPアーカイブとして、または最小限の例のZIPアーカイブとして、テスト/再生用の完全なコードダウンロードが利用可能です。前方宣言とMOCのためにファイルを分割する必要がありました。テストするためにMakefileを追加しました。depsを作成します:g ++、moc、Qt。

重要な部分

class A; // forward declaration necessary, see explanation above

class B : public QObject {
    Q_OBJECT
    Q_PROPERTY(A a READ GetA) // <-- ERROR HERE
    // ...

public slots:
    A* GetA() { 
        return mA; 
    }

private:
    A* mA;
    // ...
}

スクリプトのエラー行:

print(bObj.GetA().GetName());

コンパイルエラー

上記のQ_PROPERTYをコメントアウトすると、このエラーは消えます。

tmp/B.moc.hpp:95:51: error: invalid use of incomplete type ‘struct A’
tmp/../B.hpp:10:7: error: forward declaration of ‘struct A’

スクリプト例外

Q_PROPERTYを省略し、スクリプトからスロットとしてGetA()メソッドを呼び出すと、次の例外が発生します。

Line 7: "TypeError: cannot call GetA(): unknown return type `A*' 
        (register the type with qScriptRegisterMetaType())"

これでA*を登録すると、次のqRegisterMetaType<A*>("A*");ように変更されます。

Line 7: "TypeError: Result of expression 'bObj.GetA().GetName' 
        [undefined] is not a function." 

これは、GetA()がAオブジェクトを返さないか、何らかの方法でポインターを返すことを示していますが、スクリプトはそれを逆参照できません。GetA()は実際にを返しますがQVariant(A*)、これはどういうわけか使用できますか?

質問:

  1. どういうわけか不完全な型からQ_PROPERTYを作成できますか、または前方宣言を回避するにはどうすればよいですか?
  2. スロットで参照を返すことはできますか(たとえば、ポインタをラップし、operator.類似したものが存在する場合はスクリプトを「オーバーライド」するクラスなど、いくつかのトリック)または
  3. QtScriptでQVariant(A *)をAに逆参照することはできますか?
4

1 に答える 1

6
  1. プロパティタイプはAではなくA*、です。そのため、非常に妥当なエラーが発生します。
  2. を使用する必要がありますQScriptValue。このコードを見てください。正常に動作します:

    class A; // forward declaration necessary, see explanation above
    
    class B : public QObject
    {
        Q_OBJECT
    
        // Using QScriptValue, made from A instead of A to allow script work correctly with an object
        Q_PROPERTY(QScriptValue a READ GetA) 
    
    public slots:
        QScriptValue GetA() {
            //making QScriptValue from A. Type conversion in C style only due to limitation of incomplete type
            //In real app it's beter to put defenition of this slot after A's defenition
            return static_cast<QScriptEngine*>(parent())->newQObject((QObject*)mA);
        }
    
    private:
        A* mA;
        // ...
    public:
        //I decided my object will be a child of scriptEngine, but you can take a pointer to it in some other way
        B(QScriptEngine * parent);
    };
    
    class A: public QObject
    {
        Q_OBJECT
    public slots:
        QString GetName() const {return "a name";}
    public:
        A(QScriptEngine*parent):QObject(parent){}
    
    };
    
    B::B(QScriptEngine *parent):QObject(parent), mA(new A(parent)){}
    
于 2011-08-05T20:43:22.970 に答える