QScriptValue 作为全局对象的深层复制
我有一个使用 QtScript 进行自动化的程序。我在脚本引擎的全局范围中添加了一堆 C++ 函数和类,以便脚本可以访问它们,如下所示:
QScriptValue fun = engine->newFunction( systemFunc );
engine->globalObject().setProperty( "system", fun );
我希望能够连续运行多个脚本,每个脚本都有一个新的全局状态。因此,如果一个脚本设置了一个全局变量,就像
myGlobalVar = "stuff";
我希望在下一个脚本运行之前删除该变量一样。我执行此操作的方法是制作脚本引擎的全局对象的深层副本,然后在脚本完成运行时恢复它。但深层复制不起作用,因为我的 system
函数突然因错误而中断:
TypeError: Result of expression 'system' [[object Object]] is not a function.
这是我的深层复制函数,改编自:
http://qt.gitorious.org/qt-labs /scxml/blobs/master/src/qscxml.cpp
QScriptValue copyObject( const QScriptValue& obj, QString level = "" )
{
if( obj.isObject() || obj.isArray() ) {
QScriptValue copy = obj.isArray() ? obj.engine()->newArray() : obj.engine()->newObject();
copy.setData( obj.data() );
QScriptValueIterator it(obj);
while(it.hasNext()) {
it.next();
qDebug() << "copying" + level + "." + it.name();
if( it.flags() & QScriptValue::SkipInEnumeration )
continue;
copy.setProperty( it.name(), copyObject(it.value(), level + "." + it.name()) );
}
return copy;
}
return obj;
}
(放入 SkipInEnumeration
是为了避免无限循环)
编辑:我认为问题的一部分在于调试器中(QScriptEngineDebugger),我添加的函数和构造函数应该显示为 Function
类型,但复制后,它们显示为 Object
类型。我还没有找到一种好方法来创建一个复制现有函数的新函数(QScriptEngine::newFunction 采用实际的函数指针)。
I have a program using QtScript for some automation. I have added a bunch of C++ functions and classes to the global scope of the script engine so that scripts can access them, like so:
QScriptValue fun = engine->newFunction( systemFunc );
engine->globalObject().setProperty( "system", fun );
I would like to be able to run multiple scripts in succession, each with a fresh global state. So if one script sets a global variable, like
myGlobalVar = "stuff";
I want that variable to be erased before the next script runs. My method for doing this is to make a deep copy of the script engine's Global Object, and then restore it when a script finishes running. But the deep copies aren't working, since my system
function suddenly breaks with the error:
TypeError: Result of expression 'system' [[object Object]] is not a function.
Here is my deep copy function, adapted from:
http://qt.gitorious.org/qt-labs/scxml/blobs/master/src/qscxml.cpp
QScriptValue copyObject( const QScriptValue& obj, QString level = "" )
{
if( obj.isObject() || obj.isArray() ) {
QScriptValue copy = obj.isArray() ? obj.engine()->newArray() : obj.engine()->newObject();
copy.setData( obj.data() );
QScriptValueIterator it(obj);
while(it.hasNext()) {
it.next();
qDebug() << "copying" + level + "." + it.name();
if( it.flags() & QScriptValue::SkipInEnumeration )
continue;
copy.setProperty( it.name(), copyObject(it.value(), level + "." + it.name()) );
}
return copy;
}
return obj;
}
(the SkipInEnumeration
was put in to avoid an infinite loop)
EDIT: Part of the problem, I think, is that in the debugger (QScriptEngineDebugger), the functions and constructors I've added are supposed to appear as type Function
, but after copying, they appear as type Object
. I haven't yet found a good way of creating a new Function that duplicates an existing one (QScriptEngine::newFunction takes an actual function pointer).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
为了在 QtScript 中提供多线程,我需要一种将 QScriptValue 对象深度复制到另一个 QScriptEngine 的方法,并偶然发现了这个问题。不幸的是,Dave 的代码不足以完成此任务,即使仅在一个
QScriptEngine
内进行复制,也存在一些问题。所以我需要一个更复杂的版本。这些是我在解决方案中必须解决的问题:QScriptValue
对象在与其源对象不同的QScriptEngine
中使用,因此我还需要一种真正复制例如函数的方法。它可能对其他人有用,所以这是我想出的代码:
注意:此代码使用 Qt 内部方法
QScriptValue::objectId()
。For the purpose of making multi-threading available within QtScript, I needed a way to deep-copy
QScriptValue
objects to anotherQScriptEngine
and stumbled upon this question. Unfortunately, Dave's code was not sufficient for this task, and has a few problems even when copying within only oneQScriptEngine
. So I needed a more sophisticated version. These are the problems I had to address in my solution:QScriptValue
objects are used in a differentQScriptEngine
than their source objects, I needed a way to truly copy e.g. functions as well.It might be useful for someone else, so here's the code I came up with:
Note: This code uses the Qt-internal method
QScriptValue::objectId()
.我成功了。这是解决方案,以防对其他人有用:
重要的部分是添加
!obj.isFunction()
检查,它只会按原样复制函数,而不进行深层复制。这里的微妙之处在于,如果该项目是一个函数,isObject()
将返回 true,而这是我们不想要的。这在 Qt 文档中有记录,我不久前偶然发现了它。此外,此检查无需避免复制标记为
SkipInEnumeration
的项目。通过检查函数并按原样复制它们来修复无限循环。保留SkipInEnumeration
实际上破坏了其他一些东西,例如eval
函数和一堆其他内置函数。I got it working. Here's the solution in case it's useful for anyone else:
The important part is the addition of the
!obj.isFunction()
check, which will just copy Functions as they are, and not do a deep copy. The subtlety here is thatisObject()
will return true if the item is a Function, which we don't want. This is documented in the Qt docs and I stumbled upon it a few moments ago.Also, this check removed the need to avoid copying items marked
SkipInEnumeration
. The infinite loop is fixed by checking for functions and copying them as-is. Leaving in theSkipInEnumeration
actually broke some other stuff, like theeval
function and a bunch of other built-ins.