简体   繁体   中英

N-API wrap not finding function

I have a simple N-API wrapper around a C++ class. The class is getting instantiated and deconstructed, but the instance variable in the class is not being declared, ie the stdout shows the exports do not contain "App.m_variable".

I've read through all the doc https://nodejs.org/api/n-api.html#n_api_napi_define_class , I've gone down all of the google sites that mention "napi_define_class".

no joy.

Any help would be greatly appreciated!

node -v
v12.19.0
   
lsb_release -a
Description:    Ubuntu 20.04.1 LTS

// file: app.h
class App
  {
  public:
    double m_variable = 3.0;
    void hello();
  };

// file: index.cpp
// handle App() destructor
void n_app_dtor(napi_env env, void* instance, void* /* hint */)
  {
  std::cout << "jax: " << "n_app_dtor instance=" << instance << std::endl;
  delete ((App*) instance);
  }

// handle new App()
napi_value n_app_new(napi_env env, napi_callback_info info)
  {
  <snip>
  napi_status status;
  napi_value  n_result;
  status = napi_create_object(env, &n_result);
  if (status != napi_ok) <snip...>
    
  App* instance = new App();
  std::cout << "jax: " << "n_app_new instance=" << instance << std::endl;

  status = napi_wrap(env, n_result, (void*) instance, n_app_dtor, nullptr, nullptr);
  if (status != napi_ok) <snip...>
  return n_result;
  }

// handle get of App::m_variable
napi_value n_app_get_m_variable(napi_env env, napi_callback_info info)
  {
  std::cout << "jax: " << "n_app_get_m_variable " << std::endl;
  <snip>
  App* instance;
  napi_status status;
  status = napi_unwrap(env, argv[0], (void**) &instance);
  if (status != napi_ok) <snip...>
  
  std::cout << "jax: " << "n_app_get_m_variable instance=" << instance << std::endl;
  napi_value n_result;
  status = napi_create_double(env, instance->m_variable, &n_result);
  if (status != napi_ok) <snip...>
  return n_result;
  }

napi_value Init(napi_env env, napi_value exports)
  {
  napi_status              status;
  napi_property_descriptor properties[] = {
    {"m_variable", nullptr, nullptr, n_app_get_m_variable, nullptr, nullptr, napi_default, nullptr},
  };

  napi_value n_result;
  status = napi_define_class(env, "App", NAPI_AUTO_LENGTH, n_app_new, nullptr, 1, properties, &n_result);
  if (status != napi_ok) <...>
    
  status = napi_set_named_property(env, exports, "App", n_result);
  if (status != napi_ok) <...>
    
  return exports;
  }
NAPI_MODULE(example, Init);


# test.js
    console.log("jax: js App proto:", example.App.prototype)
    app = new example.App();
    console.log("jax: js app:", app)
    console.log("jax: js app.m_variable :", app.m_variable)
    
# output
$ node test.js
jax: js App proto: App {}
jax: n_app_new instance=0x4a4caf0
jax: js app: {}
jax: js app.m_variable : undefined
jax: n_app_dtor instance=0x4a4caf0

You can see that there's good evidence that napi_define_class() is working ok:

  • the App() instance is being called and created
  • the destructor is being called and working
  • the class is being exported

But the properties, specifically m_variable, should be showing up in the exports. So there might be something wrong with the napi_property_descriptor definition?

Also note that the call to n_app_get_m_variable and the stdout should have a log line showing it was called. But that doesn't happen.

Note for the attributes parameter I have tried a bunch of different values:

  • napi_default
  • napi_configurable
  • napi_static
  • napi_enumerable

My bad.

I made the assumption (for some reason) that the "this" pointer was argument zero when an object's member function was called (ie like python). And when a static or non-member function was called, then it isn't passed in.

That assumption is wrong.

In fact, the "this" pointer is retrieved separately from argc/argv in the call to napi_get_cb_info(), ie it is "jsthis" in this call:

napi_status status = napi_get_cb_info(env, info, &argc, argv, jsthis, nullptr);

I have published example code here: swig_example_cpp . This repo goes a little farther and shows how to use SWIG for Python and ruby, use N-API for javascript and use CMake within CLion. In any case, the N-API code is in javascript directory, see nwrap.h and index.cpp.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM