问题
我正在制作一个项目,使用 Q_OBJECT 和 Q_PROPERTY 从脚本中访问一些对象。我有两个问题:
- 使使用前向声明的类可编写脚本
- 将属性作为指针返回
解释
1. 为什么要前向声明?
类 B 获得对 A 的前向声明,因为由于模板,A 需要头部中的完整 B 类型。B 只需要头部中的不完整类型(A*),因此前向声明是有效的。
2. 为什么要返回一个指针?
我们无法返回副本,因为我们需要访问脚本中的实际对象。我们不能返回引用,因为Qt 不允许槽返回引用- 它们的类型将被忽略,它们只会返回 void*。
代码
可以在 pastebin或 ZIP 存档或最小示例的ZIP 存档上下载完整的代码,用于测试/播放:我需要为前向声明和 MOC 拆分文件。我添加了一个 Makefile 来测试它。制作部门: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() 然后实际上返回 a QVariant(A*)
,这可以以某种方式使用吗?
问题:
- 我可以以某种方式从不完整的类型中创建 Q_PROPERTY,或者如何避免前向声明?
- 我可以在插槽中返回一个引用吗(可能是一些技巧,例如一个包装指针并“覆盖”脚本的类
operator.
,如果存在类似的东西)或 - 我可以以某种方式将 QVariant(A*) 取消引用到 QtScript 中的 A 吗?