Я начинаю с Qt, и один из моих проектов использует QJSEngine для оценки javascript, и я хочу предоставить скрипту целый API, с классами и глобальными функциями.
Прямо сейчас моя программа предоставляет только материал по умолчанию для ECMAScript (eval, encodeURI, parseInt и т. Д.), Но мне нужно предоставить в код некоторые пользовательские классы, такие как API браузеров (класс WebSocket, класс Image, объект документа). Например:
var obj = new CustomClass("", 0);
var ret = obj.customClassMethod("[...]!");
customFunction(ret);
Мне нужно определить поведение классов в C ++, это не поможет оценить определение классов и позволит запустить пользовательский код.
В отличие от 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: Я бы добавил больше ссылок на официальную документацию, но из-за отсутствия репутации мне это запрещено.
Если вы посмотрите документацию по QScriptEngine или поищете «Примеры QScriptEngine», вы можете найти некоторые сведения о том, как сделать пользовательские классы C ++ доступными для QScriptEngine.
Вот хорошее место для начала:
ссылка на пример
QScriptEngine очень похож на QJsEngine, поэтому он не должен быть для вас большой проблемой.
Надеюсь это поможет 🙂