Как создать API с QJSEngine?

Я начинаю с Qt, и один из моих проектов использует QJSEngine для оценки javascript, и я хочу предоставить скрипту целый API, с классами и глобальными функциями.

Прямо сейчас моя программа предоставляет только материал по умолчанию для ECMAScript (eval, encodeURI, parseInt и т. Д.), Но мне нужно предоставить в код некоторые пользовательские классы, такие как API браузеров (класс WebSocket, класс Image, объект документа). Например:

var obj = new CustomClass("", 0);
var ret = obj.customClassMethod("[...]!");
customFunction(ret);

Мне нужно определить поведение классов в C ++, это не поможет оценить определение классов и позволит запустить пользовательский код.

1

Решение

В отличие от QScriptEngineгде вы можете добавить пользовательские классы, если они наследуются от QObject используя Q_SCRIPT_DECLARE_QMETAOBJECT макрос, QJSEngine не предоставляет эту функцию напрямую.

Вы все еще можете использовать мета-объектную систему Qt для предоставления интерфейсов для Javascript, но вам нужно создать экземпляр объекта в C ++ и добавить его в контекст Javascript.
Тогда это слоты, методы, определенные с Q_INVOKABLEи свойства, определенные с Q_PROPERTY все доступны из среды выполнения Javascript.

Теперь вы можете создать фабрику, которая создает экземпляры вашего пользовательского класса CustomClass для данного QJSEngine обернутый как объекты Javascript:

class CustomClassFactory : public QObject
{
Q_OBJECT
public:
CustomClassFactory(QJSEngine* engine) : m_engine(engine) {}
Q_INVOKABLE QJSValue createInstance() {
// The engine takes ownership and destroys the object if no longer required.
return m_engine->newQObject(new CustomClass());
}
private:
QJSEngine* m_engine;
}

Экземпляр фабрики должен быть создан и добавлен к глобальному объекту среды выполнения Javascript:

QJSEngine engine;
QJSValue factoryObj = engine.newQObject(new CustomClassFactory());
engine.globalObject().setProperty("_customClassFactory", factoryObj);

Теперь мы можем создавать объекты в Javascript с помощью:

var obj = _customClassFactory.createInstance()

Поскольку мы зашли так далеко, давайте дополнительно добавим конструктор для пользовательского класса в среду выполнения Javascript:

QJSEngine engine;
// Again, the QJSEngine will take ownership of the created object.
QJSValue factoryObj = engine.newQObject(new CustomClassFactory());
engine.globalObject().setProperty("_customClassFactory", factoryObj);
engine.evaluate(
"function CustomClass() {""    return _customClassFactory.createInstance()""}");

И наконец, теперь вы можете создавать объекты C ++ в Javascript, как если бы вы использовали пользовательские классы Javascript:

var obj = new CustomClass()

Для упомянутых WebSocket API вы можете обернуть QtWebSocket для этого — это было именно то, что мне нужно, когда я предложил предложенный подход.

Обратите внимание, что для простоты я опустил параметры для конструктора, но они также могут быть просто добавлены.

PS: Я бы добавил больше ссылок на официальную документацию, но из-за отсутствия репутации мне это запрещено.

3

Другие решения

Если вы посмотрите документацию по QScriptEngine или поищете «Примеры QScriptEngine», вы можете найти некоторые сведения о том, как сделать пользовательские классы C ++ доступными для QScriptEngine.

Вот хорошее место для начала:
ссылка на пример

QScriptEngine очень похож на QJsEngine, поэтому он не должен быть для вас большой проблемой.

Надеюсь это поможет 🙂

0

По вопросам рекламы [email protected]