问题
我正在使用Q_OBJECT和Q_PROPERTY制作一个项目,以便从脚本中访问一些对象。我有两个问题:
- 如何使使用前置声明的类可脚本化
- 如何返回指针属性
解释
1. 为什么需要前置声明?
类B获取了A的前置声明,因为由于模板,A需要在头文件中包含完整的B类型。B只需要不完整类型(A*),因此前置声明是有效的。
2. 为什么要返回指针?
我们不能返回副本,因为我们需要访问脚本中的实际对象。我们不能返回引用,因为Qt不允许槽函数返回引用——它们的类型将被忽略,它们只会返回void*。
代码
可以在pastebin上下载完整代码或者下载ZIP压缩包或者最小示例的ZIP压缩包进行测试/玩耍:我需要分开文件来处理前置声明和MOC。我添加了一个Makefile以进行测试。Make依赖项: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())"
当使用qRegisterMetaType<A*>("A*")
注册A*时,这将变成:
Line 7: "TypeError: Result of expression 'bObj.GetA().GetName'
[undefined] is not a function."
这表明GetA()函数并不返回A对象,或者以某种方式返回指针,但脚本无法解引用它。 GetA()实际上返回一个QVariant(A*)
,是否可以以某种方式使用它?
问题:
- 我能否从不完整的类型中创建Q_PROPERTY,或者如何避免前向声明?
- 我能否在槽函数中返回引用(也许有一些技巧,比如包装指针并“覆盖”脚本
operator.
的类,如果存在类似的东西) - 我能否以某种方式将QVariant(A*)解引用为QtScript中的A类型?