#include <QJSEngine>
#include <QThread>
class QJSEngineWrapper : public QObject
{
Q_OBJECT
QJSEngine* m_engine;
public:
QJSEngineWrapper(QObject *parent = Q_NULLPTR);
void call(QJSValue value, const QJSValueList& args = QJSValueList());
QJSValue evaluate(const QString &program, const QString &fileName = QString(), int lineNumber = 1) {
return m_engine->evaluate(program, fileName, lineNumber);
}
inline void installExtensions(QJSEngine::Extensions extensions, const QJSValue &object = QJSValue()) {
m_engine->installExtensions(extensions, object);
}
signals:
void call_signal(QJSValue, const QJSValueList& args);
private slots:
inline void call_imp(QJSValue value, const QJSValueList& args) {
value.call(args);
}
};
#include "qjsenginewrapper.h"
QJSEngineWrapper::QJSEngineWrapper(QObject *parent)
: QObject(parent)
{
m_engine = new QJSEngine(this);
connect(this, &QJSEngineWrapper::call_signal, this, &QJSEngineWrapper::call_imp, Qt::QueuedConnection);
}
void QJSEngineWrapper::call(QJSValue value, const QJSValueList &args)
{
if (QThread::currentThread() != thread())
emit call_signal(value, args);
else
call_imp(value, args);
}
#include <QCoreApplication>
#include <QTimer>
#include "qjsenginewrapper.h"
int main(int argc, char** argv)
{
qRegisterMetaType<QJSValueList>("QJSValueList");
QCoreApplication app(argc, argv);
QJSEngineWrapper engine;
engine.installExtensions(QJSEngine::ConsoleExtension);
engine.evaluate("var iteration = 0;");
auto function = engine.evaluate("(function() { if (++iteration % 100 == 0) console.log(iteration); })");
QThread thread;
thread.start();
QTimer timer;
QObject::connect(&timer, &QTimer::timeout, &engine, [&]{ engine.call(function); }, Qt::DirectConnection);
timer.moveToThread(&thread);
QMetaObject::invokeMethod(&timer, "start", Q_ARG(int, 0));
return app.exec();
}
class ThreadSafeQJSEngine : public QObject
{
// ...
public:
void call(QJSValue value, const QJSValueList& args);
signals:
void call_signal(QJSValue, const QJSValueList& args);
private slots:
inline void call_imp(QJSValue value, const QJSValueList& args) {
if (value.engine() == m_engine) value.call(args);
}
// ...
};
// ....
ThreadSafeQJSEngine::ThreadSafeQJSEngine(QObject *parent)
: QObject(parent)
{
m_engine = new QJSEngine;
connect(this, &ThreadSafeQJSEngine::call_signal, this, &ThreadSafeQJSEngine::call_imp, Qt::QueuedConnection);
}
// ...
void ThreadSafeQJSEngine::call(QJSValue value, const QJSValueList &args)
{
if (QThread::currentThread() != thread())
emit call_signal(value, args);
else
call_imp(value, args);
}