如何将不属于 QObject 的枚举暴露给 QJSEngine?
How to expose enum not owned by QObject to QJSEngine?
我正在为我的软件编写脚本包装器,这样我就可以通过脚本控制我的软件。包装类的目的是将脚本接口与实际类分开,因为我可能不想公开类的所有信号和插槽。我正在使用Qt 5.13和QJSEngine。
我的问题是,根据我所阅读的内容和我的实验,似乎为了能够公开枚举,它需要在继承 QObject 并通过 newQObject((/setProperty(( 公开的类中。但是,我不想在下面的示例中公开类 Foo,但我仍然想向脚本环境公开枚举 Foo::Bar。我该怎么做?Q_ENUM似乎假设枚举在 QObject 中,并且 QObject 在脚本环境中公开(属性(。下面是我正在做的一个简短的例子(我希望能够从脚本环境中调用 FooWrapper::slot1((:
class Foo : public QObject
{
Q_OBJECT
public:
Foo(QJSEngine& engine)
{
auto wrapper = new FooWrapper(this, engine);
}
enum class Bar
{
VAL1,
VAL2
};
public slots:
void slot1(Bar bar);
void slot2();
};
class FooWrapper : public QObject
{
Q_OBJECT
public:
Foo(Foo& foo, QJSEngine& engine)
: foo(&foo)
{
QJSValue obj = engine.newQObject(this);
auto gObj = engine.globalObject();
gObj.setProperty("foo", obj);
}
public slots:
void slot1(Bar bar)
{
foo->slot1(bar);
}
private:
Foo* foo;
};
好吧,对于 OP 的 Dago(对不起!万一其他人遇到这种情况...
一个选项与一般的 QML 相同,即可以从命名空间注册枚举和标志。使用 Q_ENUM_NS()
和 Q_FLAG_NS()
(对于标志,Q_DECLARE_FLAGS()
调用保持不变,也Q_DECLARE_OPERATORS_FOR_FLAGS()
命名空间外部,与类相同,如果需要的话(。
这里有我的相关答案: 如何从 QML 访问C++枚举?
但是对于纯JSEngine
使用,只需将命名空间的QMetaObject
设置为引擎中的属性就足够了......不需要qmlRegisterUncreatableMetaObject...
的东西。
所以总结一下...
#include <QObject> // required for the macros below
namespace MyNamespace
{
Q_NAMESPACE // required for meta object creation
enum class Bar {
VAL1,
VAL2,
};
Q_ENUM_NS(Bar) // register the enum in meta object data
}
// declare the enum's meta type (required if enum will be used in
// methods/functions exposed to JS.
Q_DECLARE_METATYPE(MyNamespace::Bar)
稍后在某处的QJSEngine
初始化例程中...
QJSEngine *jse = new QJSEngine();
...
// Register the namespace's meta object as a property of the global
// object (or any other object's property for that matter).
// The property name doesn't have to match the namespace name.
jse->globalObject().setProperty(
"MyNamespace",
jse->newQMetaObject(&MyNamespace::staticMetaObject)
);
然后在 JS 环境中,枚举可用作命名空间本身的属性。
QJSValue v = jse->evaluate("MyNamespace.VAL2"); // v.toInt() == 1
或在脚本中...
console.log('>>', MyNamespace.VAL2); // output: >> 1
另一种选择可能是将枚举保留在类中,并将类的QMetaObject
注册为引擎的属性......只是不要将构造函数(或任何其他静态方法(标记为Q_INVOKABLE
。
HTH,
-Max
参考资料:
https://doc.qt.io/qt-6/qjsengine.html#newQMetaObject
https://doc.qt.io/qt-6/qobject.html#Q_NAMESPACE
https://doc.qt.io/qt-6/qobject.html#Q_ENUM_NS
我找不到对注册命名空间元对象的直接引用,正如我刚才描述的那样...... 我向你保证它可以工作(并且有很多版本(。
在本节末尾,这里模糊地引用了它。 https://doc.qt.io/qt-5/qqmlengine.html#QML_ELEMENT
另一个更不相关(但可能很有趣(:https://doc.qt.io/qt-6/qqmlengine.html#QML_EXTENDED_NAMESPACE
- 使用QJsEngine在Qt中注册自定义类型
- Qt 5.11.2 (Clang 8.0 (Apple), 64 位), 找不到 QJSEngine 文件
- 如何注册枚举类型到QJSEngine,以便在脚本环境中使用?
- 编译了一个recent-C++.因此,如果没有暴露std符号,请在旧系统上运行
- 如何将不属于 QObject 的枚举暴露给 QJSEngine?
- Cython:不暴露实施的一部分
- 将ADA API暴露于C/C (可扩展方式)
- 同步线程安全的API,用于暴露缓存数据
- 与公开暴露的标头有关的C 项目结构
- 如何清理或销毁QJSEngine?
- 在公共标头中使用非暴露类型的风险是什么?
- VULKAN,您可以直接暴露扩展名吗?
- 避免将静态变量暴露在默认函数参数中
- QJSEngine全局字符串比较
- 将C 对象暴露于QML并收听更改事件
- 如何以相同的名称暴露无法直接暴露的C 函数
- QT:将任何C 对象暴露于JavaScript
- 从链接列表中删除元素,采访暴露了图书漏洞
- 删除boost::python暴露的std::vector中的指针
- 在Cython中封装std::数组,并将其暴露给内存视图