Qt:Q_PROPERTY,带有QtScript访问的指针和前向声明

opa*_*tut 5 qt properties forward-declaration qtscript qobject

问题

我正在使用Q_OBJECT和Q_PROPERTY创建一个项目来从脚本访问一些对象.我有两个问题:

  1. 使用前向声明脚本的类
  2. 将属性作为指针返回

说明

1.为什么要前言?

B类将前向声明传递给A,因为A由于模板而需要标题中的完整B类型.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;
    // ...
}
Run Code Online (Sandbox Code Playgroud)

脚本中的错误行:

print(bObj.GetA().GetName());
Run Code Online (Sandbox Code Playgroud)

编译错误

当我注释掉上面的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’
Run Code Online (Sandbox Code Playgroud)

脚本例外

当省略Q_PROPERTY并从脚本调用GetA()方法作为插槽时,我得到以下异常:

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

注册A*时,qRegisterMetaType<A*>("A*");此更改为:

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

这表明GetA()不返回A对象,或以某种方式返回指针,但脚本无法取消引用它.GetA()然后实际返回一个QVariant(A*),这可以以某种方式使用?

问题:

  1. 我可以以某种方式从不完整的类型中创建Q_PROPERTY,或者我怎么能避免前向声明?
  2. 我可以在插槽中返回引用(可能是一些技巧,例如包装指针的类和"覆盖"脚本operator.,如果存在类似的东西)或者
  3. 我可以在QtScript中以某种方式将QVariant(A*)解引用到A吗?

Lol*_*4t0 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)){}
    
    Run Code Online (Sandbox Code Playgroud)