Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling Javascript function from a C++ callback in V8

I'm trying to call a registered JS function when a c++ callback is called, but I'm getting a segfault for what I assume is a scoping issue.

 Handle<Value> addEventListener( const Arguments& args ) {
    HandleScope scope;
    if (!args[0]->IsFunction()) {
        return ThrowException(Exception::TypeError(String::New("Wrong arguments")));
    }

    Persistent<Function> fn = Persistent<Function>::New(Handle<Function>::Cast(args[0]));
    Local<Number> num = Number::New(registerListener(&callback, &fn));
    scope.Close(num);
}

When an event happens, the following method is called. I'm assuming that this probably happens on another thread to which V8 is executing JS.

void callback(int event, void* context ) {
    HandleScope scope;
    Local<Value> args[] = { Local<Value>::New(Number::New(event)) };
    Persistent<Function> *func = static_cast<Persistent<Function> *>(context);
    (* func)->Call((* func), 1, args);

    scope.Close(Undefined());
}

This causes a Segmentation fault: 11. Note that if I call the callback function directly with a reference to Persistent from addEventListener(), it executes the function correctly.

I'm assuming that I need a Locker or Isolate? It also looks like libuv's uv_queue_work() might be able to solve this, but since I don't start the thread, I can't see how you would use it.

like image 793
marchaos Avatar asked Dec 11 '12 19:12

marchaos


People also ask

How do you call a callback function?

A custom callback function can be created by using the callback keyword as the last parameter. It can then be invoked by calling the callback() function at the end of the function. The typeof operator is optionally used to check if the argument passed is actually a function. console.

How do callback functions work JavaScript?

A JavaScript callback is a function which is to be executed after another function has finished execution. A more formal definition would be - Any function that is passed as an argument to another function so that it can be executed in that other function is called as a callback function.

What is a JavaScript callback?

A callback is a function passed as an argument to another function. This technique allows a function to call another function. A callback function can run after another function has finished.

Why callback function is used in JavaScript?

Callbacks make sure that a function is not going to run before a task is completed but will run right after the task has completed. It helps us develop asynchronous JavaScript code and keeps us safe from problems and errors.


1 Answers

I know this question is a bit old, but there has been a pretty major update in nodejs v0.10 to v0.12. V8 changed the behavior of v8::Persistent. v8::Persistent no longer inherits from v8::Handle. I was updating some code and found that the following worked...

  void resize(const v8::FunctionCallbackInfo<Value> &args) {
    Isolate *isolate = Isolate::GetCurrent();
    HandleScope scope(isolate);
    Persistent<Function> callback;
    callback.Reset(isolate, args[0].As<Function>())
    const unsigned argc = 2;
    Local<Value> argv[argc] = { Null(isolate), String::NewFromUtf8(isolate, "success") };
    Local<Function>::New(isolate, work->callback)->Call(isolate->GetCurrentContext()->Global(), argc, argv);
    callback.Reset();
  }

I believe the goal of this update was to make it harder to expose memory leaks. In node v0.10, you would have done something like the following...

  v8::Local<v8::Value> value = /* ... */;
  v8::Persistent<v8::Value> persistent = v8::Persistent<v8::Value>::New(value);
  // ...
  v8::Local<v8::Value> value_again = *persistent;
  // ...
  persistent.Dispose();
  persistent.Clear();
like image 175
Hoodlum Avatar answered Sep 18 '22 16:09

Hoodlum