我有以下用 C++ 编写的几乎可以工作的代码:
[..]
Handle<Object> jsGlobal;
Handle<Function> jsUpdateFunc;
void setupJs () {
V8::Initialize();
Isolate* isolate = v8::Isolate::New();
Isolate::Scope isolate_scope(isolate);
HandleScope handle_scope(isolate);
Local<Context> context = Context::New(isolate);
Context::Scope context_scope(context);
Local<String> source = String::NewFromUtf8(isolate, "var a = 0; function test() { a++; return a.toString(); }");
Local<Script> script = Script::Compile(source);
script->Run();
jsGlobal = context->Global();
Handle<Value> value = jsGlobal->Get(String::NewFromUtf8(isolate, "test"));
jsUpdateFunc = Handle<Function>::Cast(value);
}
void callJs() {
Handle<Value> args[0];
Handle<Value> js_result = jsUpdateFunc->Call(jsGlobal, 0, args);
js_result->ToString();
String::Utf8Value utf8(js_result);
printf("%s\n", *utf8);
}
[..]
我有函数 setupJs() 设置 v8 环境并且 callJs 应该被调用多次(工作时,javascript 脚本每次将 var a 递增 1)。
如果我把
Handle<Value> args[0];
Handle<Value> js_result = jsUpdateFunc->Call(jsGlobal, 0, args);
js_result->ToString();
String::Utf8Value utf8(js_result);
printf("%s\n", *utf8);
在 setupJs 中,我可以看到如何调用函数 s 并打印“1”。但是,如果我将函数调用保留为稍后调用的不同函数,我会在 Handle<Value> js_result = jsUpdateFunc->Call(jsGlobal, 0, args);
行出现段错误。
我检查过,jsUpdateFunc 和 jsGlobal 都是非空指针
最佳答案
您需要为 jsGlobal
和 jsUpdateFunc
使用持久句柄。普通(本地)句柄在其封闭的 v8::HandleScope
被销毁时变得无效。
您还需要一个全局变量作为 v8::Isolate
指针,另一个变量作为 v8::Context
的持久句柄。
要稍后调用脚本函数,您需要:
- 锁定隔离(您也确实应该在
setupJs
中执行此操作;请参阅v8::Locker
) - 输入隔离(参见
v8::Isolate::Scope
)。 - 建立句柄作用域(参见
v8::HandleScope
)。 - 为上下文创建本地句柄。
- 输入上下文(参见
v8::Context::Scope
)。 - 为
jsGlobal
和jsUpdateFunc
创建本地句柄。 - 如上调用脚本函数。
在 V8 头文件中查找 v8::Persistent
和相关模板。
关于C++ 作用域和 Google V8 脚本上下文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33168903/