Pergunta

I'd like to execute an anonymous Qt script function from c++ but can't figure out the QScriptContext to use.

Here's the script:

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

Here's the setTimeout method in c++:

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

The call method of the QScriptValue object requires a context and argument list:

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

edit: The context can be the global context but building the argument list to invoke the function seems to be the crux of the problem. I don't see anything that explains how to build an "argument object" from C++. There's a property called "arguments" but it doesn't seem to be filled out, or I haven't figured out how to use it.

Foi útil?

Solução

If we look at this javascript code only:

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

setTimeout is told to wait for 9000, and then invoke a the anonymous function. However, the problem is the anonymous function has a parameter. And the setTimeout function does not know what parameter to pass to the function.

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

If you try this code in chrome, it will alert undefined, because setTimeout function does not know what to pass to the anonymous function, it just passes no argument.

But if you try this:

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

It will alert Hello world, because now otherObject is no longer the parameter to the anonymous function, but a local variable which forms a closure with the anonymous function.

So in order to make your code working, the setTimeout function should be different from the setTimeout function of the browsers. If you want to set the parameter for the anonymous function from the C++ side, here is what you can do:

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);
}

For simplicity, there are three things I didn't include:

  1. The otherObjectProto is not implemented. Look here for an example.

  2. The QThread::sleep is blocking the current thread, which may not be desired, but it can easily be modified be asynchronous using QTimer.

  3. engine->newQObject has other parameters, which defines the ownership of the QObject, if you don't want memory leak, better read it.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top