Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ scope and Google V8 script context

I have the following, almost working piece of code written in 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);
}

[..]

I have the function setupJs() setup the v8 environment and callJs is supposed to be called multiple times (when working, the javascript script increments var a by one each time).

If i put

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

in setupJs, I can see how the function s called and "1" is printed. But if I leave the function call withing a different function to be called later, i have a Segfault at the line Handle<Value> js_result = jsUpdateFunc->Call(jsGlobal, 0, args);

I've checked and both jsUpdateFunc and jsGlobal are not-null pointers

like image 271
pistacchio Avatar asked Oct 16 '15 11:10

pistacchio


1 Answers

You need to use persistent handles for jsGlobal and jsUpdateFunc. A normal (local) handle becomes invalid when its enclosing v8::HandleScope is destroyed.

You'll also want a global variable for the v8::Isolate pointer and another one for a persistent handle to the v8::Context.

To call the the script function later, you need to:

  1. Lock the isolate (which you really should do in setupJs as well; see v8::Locker)
  2. Enter the isolate (see v8::Isolate::Scope).
  3. Establish a handle scope (see v8::HandleScope).
  4. Create a local handle for the context.
  5. Enter the context (see v8::Context::Scope).
  6. Create local handles for jsGlobal and jsUpdateFunc.
  7. Call the script function as above.

Look for v8::Persistent and related templates in the V8 header file.

like image 138
BitCortex Avatar answered Sep 23 '22 00:09

BitCortex