QJSEngine: печать на консоль

Я перехожу с QScriptEngine (устарело) на QJSEngine и вижу, что не могу использовать print:

  QJSEngine engine;

  QJSValue val = engine.evaluate(
        "print('123');"
        );

  if (val.isError()){
     qDebug() << "error: " << val.toString();
  }

  qDebug() << "val: " << val.toVariant();

Результат:

error:  "ReferenceError: print is not defined"

В QScriptEngine работает.

Тогда как напечатать что-нибудь для консоли в QJSEngine? В документах ничего не нашел. Я пытался использовать console.log, но console тоже не определен.


person Dmitry Frank    schedule 16.08.2015    source источник


Ответы (2)


Функция печати не реализована в QJSEngine. Вам придется реализовать его самостоятельно. К счастью, вы можете написать объекты QObject и сделать их доступными в своем сценарии. (См. раздел «Интеграция QObject» по адресу http://doc.qt.io/qt-5/qjsengine.html)

Вот как я это сделал:

Создайте класс JConsole, наследуемый от QObject:

Ваш собственный консольный класс

jsconsole.h

#ifndef JSCONSOLE_H
#define JSCONSOLE_H

#include <QObject>

class JSConsole : public QObject
{
    Q_OBJECT
public:
    explicit JSConsole(QObject *parent = 0);

signals:

public slots:
    void log(QString msg);
};

#endif // JSCONSOLE_H

jsconsole.cpp

#include "jsconsole.h"
#include <QDebug>


JSConsole::JSConsole(QObject *parent) :
    QObject(parent)
{
}

void JSConsole::log(QString msg)
{
    qDebug() << "jsConsole: "<< msg;
}

Используй это

Теперь вы создаете прокси-объект в движке js, используя QJSEngine.newQObject. После этого вы добавляете его в свой глобальный объект и используете.

QJSEngine engine;
JSConsole console;
QJSValue consoleObj =  engine.newQObject(&console);
engine.globalObject().setProperty("console", consoleObj);
QJSValue result = engine.evaluate("console.log('test');");

Регистрация ошибок

Я долго искал ошибки в своем коде на С++, когда я только что сделал орфографическую ошибку в своем файле js. Следующий фрагмент помог бы избежать этого.

if (result.isError())
{
    qDebug() << "result: " << result.property("lineNumber").toInt() << ":" << result.toString();
}

PS: Первый пост после долгих лет ожидания. Я читал советы по написанию отличных ответов, но если я допустил какие-то ошибки/плохие вещи, скажите мне.

Да пребудет с вами код

person nitroxleecher    schedule 04.09.2015
comment
РЕДАКТИРОВАТЬ: Насколько я понял, чтобы сделать методы доступными из сценария, вы должны определить их как слоты. - person nitroxleecher; 05.09.2015
comment
Если наличие методов из скриптов - единственная причина сделать их слотами, то лучше объявить их макросом Q_INVOKABLE: так будет понятнее показать замысел программиста. Спасибо за ответ. И добро пожаловать в СО. - person Dmitry Frank; 05.09.2015
comment
Это действительно помогает. Доступно очень мало документации об этом (и QJS Engine в целом) - person Ben Non; 17.09.2015

Начиная с Qt 5.6 решение еще проще: можно установить расширения Javascript. Одним из таких расширений является консоль, которая предоставляет функцию print:

QJSEngine myEngine;
myEngine.installExtensions(QJSEngine::ConsoleExtension);
myEngine.eval("print(1 + 2)");
person Mehrwolf    schedule 03.05.2016