Контекст для анонимной функции сценария qt?

Я хотел бы выполнить анонимную функцию сценария Qt из C++, но не могу понять, какой QScriptContext использовать.

Вот сценарий:

{
  otherObject.Text = "Hello World";
  setTimeout(function(otherObject) { otherObject.Text = "Goodbye World"; }, 9000 );
}

Вот метод setTimeout в C++:

QScriptValue setTimeout( QScriptContext* ctx, QScriptEngine* eng )
{
  // How can I obtain the correct context and arg list for the anonymous function here?
}

Метод вызова объекта QScriptValue требует контекста и списка аргументов:

call( ctx->thisObject(), ctx->argumentsObject() );

редактировать: контекст может быть глобальным контекстом, но суть проблемы заключается в создании списка аргументов для вызова функции. Я не вижу ничего, что объясняет, как построить "объект аргумента" из C++. Есть свойство, называемое "аргументы", но оно, похоже, не заполнено, или я не понял, как его использовать.

1 ответ

Решение

Если мы посмотрим только на этот код JavaScript:

{
    otherObject.Text = "Hello World";
    setTimeout(function(otherObject) { otherObject.Text = "Goodbye World"; }, 9000 );
}

setTimeout говорят, что нужно ждать 9000, а затем вызывать анонимную функцию. Однако проблема в том, что анонимная функция имеет параметр. И функция setTimeout не знает, какой параметр передать функции.

<html>
<script>
var otherObject = 'Hello World';
setTimeout(function(otherObject){alert(otherObject);}, 1000);
</script>
</html>

Если вы попробуете этот код в chrome, он выдаст предупреждение undefined, потому что функция setTimeout не знает, что передать анонимной функции, она просто не передает аргументов.

Но если вы попробуете это:

<html>
<script>
var otherObject = 'Hello World';
setTimeout(function(){alert(otherObject);}, 1000);
</script>
</html>

Это предупредит Hello world, потому что теперь otherObject больше не является параметром для анонимной функции, а является локальной переменной, которая образует замыкание с анонимной функцией.

Таким образом, чтобы ваш код работал, функция setTimeout должна отличаться от функции setTimeout браузеров. Если вы хотите установить параметр для анонимной функции со стороны C++, вот что вы можете сделать:

QScriptValue setTimeout( QScriptContext* ctx, QScriptEngine* eng )
{
    QScriptValue anonymous_callback = ctx->argument(0);
    QScriptValue time = ctx->argument(1);
    QThread::sleep(time.toInt32())
    // Then Invoke the anonymous function:
    QScriptValueList args;
    otherObjectProto * otherObjectQtSide = new otherObjectProto();
    otherObjectQtSide.setProperty("Text","Goodbye World!");
    QScriptValue otherObject = engine->newQObject(otherObjectQtSide);// engine is pointer to the QScriptEngine instance
    args << otherObject;
    anonymous_callback.call(QScriptValue(),args);
}

Для простоты есть три вещи, которые я не включил:

  1. OtherObjectProto не реализовано. Посмотрите здесь для примера.

  2. QThread::sleep блокирует текущий поток, что может быть нежелательно, но его можно легко изменить, используя асинхронный QTimer.

  3. engine-> newQObject имеет другие параметры, которые определяют владение QObject. Если вы не хотите утечки памяти, лучше прочитайте ее.

Другие вопросы по тегам