Функция обертывания N-API не найдена
У меня есть простая оболочка N-API для класса C++. Класс создается и деконструируется, но переменная экземпляра в классе не объявляется, т. Е. Стандартный вывод показывает, что экспорт не содержит "App.m_variable".
Я прочитал весь документ https://nodejs.org/api/n-api.html#n_api_napi_define_class, просмотрел все сайты Google, на которых упоминается "napi_define_class".
без радости.
Любая помощь будет принята с благодарностью!
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
Вы можете видеть, что есть веские доказательства того, что napi_define_class() работает нормально:
- экземпляр App() вызывается и создается
- деструктор вызывается и работает
- класс экспортируется
Но свойства, в частности m_variable, должны отображаться в экспорте. Может быть, что-то не так с определением napi_property_descriptor?
Также обратите внимание, что при вызове n_app_get_m_variable и stdout должна быть строка журнала, показывающая, что он был вызван. Но этого не происходит.
Обратите внимание на параметр атрибутов, который я пробовал несколько разных значений:
- napi_default
- napi_configurable
- napi_static
- napi_enumerable
1 ответ
Виноват.
Я сделал предположение (по какой-то причине), что указатель "this" был нулевым аргументом, когда вызывалась функция-член объекта (например, как python). И когда была вызвана статическая функция или функция, не являющаяся членом, она не передается.
Это предположение неверно.
Фактически, указатель this извлекается отдельно из argc/argv при вызове napi_get_cb_info(), то есть в этом вызове это jsthis:
napi_status status = napi_get_cb_info(env, info, &argc, argv, jsthis, nullptr);
Я опубликовал здесь пример кода: swig_example_cpp. Это репо идет немного дальше и показывает, как использовать SWIG для Python и ruby, использовать N-API для javascript и использовать CMake в CLion. В любом случае код N-API находится в каталоге javascript, см. Nwrap.h и index.cpp.