Search code examples
javascriptc++swigv8

NodeJS function called from v8 SWIG C++ seg. faults


I have some c++ code which I am compiling with SWIG (you can clone the code here), it defines the javascript "theFunction" which will be executed from C++ once setup :

v8::Persistent<v8::Function> theFunction;

/** Class to test the wasm setup
*/
class Test {
...
}

I am extending it in my swig Test.i template to setup the javascript callback so that C++ can call it like so :

%extend Test {

  void setCallback(const std::string& fnName){
    SWIGV8_HANDLESCOPE();

    v8::Isolate* isolate = v8::Isolate::GetCurrent();

    // first find the global js function
    v8::Local<v8::Value> fnObj = SWIGV8_CURRENT_CONTEXT()->Global()->Get(SWIGV8_CURRENT_CONTEXT(), v8::String::NewFromUtf8(isolate, fnName.c_str())).ToLocalChecked();

    if (!fnObj->IsFunction()){
      printf("setupCallback : error no function found\n");
      return;
    } else
      printf("setupCallback : %s function found\n", fnName.c_str());

    v8::Local<v8::Function> func = v8::Local<v8::Function>::Cast(fnObj);
    theFunction.Reset(isolate, func);

    // now call the global javascript function from C++
    v8::Local<v8::Function> func2 = v8::Local<v8::Function>::New(isolate, theFunction);
    if (!func2.IsEmpty()) {
      const unsigned argc = 1;
      v8::Local<v8::Value> argv[argc] = { v8::String::NewFromUtf8(isolate, "hello world") };
      v8::Local<v8::Value> ret;
      func2->Call(SWIGV8_CURRENT_CONTEXT(), ret, argc, argv);
     }
  }
}

When I run my javascript, the function is found from the globals but it hange when C++ tries to execute it :

global.fnName = function (str) {
  console.log(str);
}

test.setCallback("fnName");

But unfortunately C++ seg. faults before executing the javascript "theFunction" :

setupCallback : fnName function found
Segmentation fault (core dumped)

Is there something missing from the v8 code to make the callback work ?

In the supplied test code, the file swigCNodejw_wrap_wrap.cxx is autogenerated which has the v8 code inside.


Solution

  • Change the following Call method :

    func2->Call(SWIGV8_CURRENT_CONTEXT(), ret, argc, argv);
    

    To this :

    func2->Call(SWIGV8_CURRENT_CONTEXT(), func2, argc, argv);