2

I'm trying to initialize my node addon module using JS callback for logging. Initialize method is intended to store callback value for calling from other methods. So I add reference to the callback using napi_create_reference.

But when I'm trying to call the callback from my second addon method MyAddonMethod I receive napi_invalid_arg error.

I've tried to investigate the issue. The call to napi_typeof for the callback value from MyAddonMethod returns napi_invalid_arg too. Looks like the callback value was garbage collected despite my strong reference.

What am I doing wrong? Does napi_create_reference actually prevents callback object from being garbage collected between addon calls?

// JS side:
const addon = require('./addon.node');
function logCallbackFunction(logLine)
{
    console.log("Trace: " + logLine);
}
addon.Initialize(logCallbackFunction);
addon.MyAddonMethod();

// C++ side
// Initialize method:
napi_ref ref;
napi_create_reference(env, value, 1, &ref);
g_Value = value; // store the value somewhere between calls

// MyAddonMethod method: // "env" doesn't change from call to call
napi_valuetype type;
napi_status stat = napi_typeof(env, g_Value, &type); // napi_invalid_arg
quinz
  • 1,282
  • 4
  • 21
  • 33
  • I haven't tried to do this, nor do I use N-API directly (I stick with C++ and node-addon-api). But have you tried passing a reference count of 2 rather than 1? The doc doesn't say, but there is already 1 reference - the JavaScript reference, so if napi_create_reference doesn't add another and just uses the 1 you pass as an arg that might explain things. – bmacnaughton Jul 06 '19 at 00:43
  • maybe post a bit more code - it's not clear what value is, nor what g_Value is. if there is enough code to compile it would make it easier to take a look at. – bmacnaughton Jul 06 '19 at 00:49
  • For sure I've tried 2 rather than 1. Results are the same. g_Value has type napi_value. Did you try to save the reference to the js function/object between node addon calls? What node-addon-api method you used? – Alexey Ilyushin Jul 08 '19 at 14:07
  • this might be helpful: https://github.com/nodejs/node-addon-api/blob/master/doc/function.md – bmacnaughton Jul 08 '19 at 14:41
  • and here's an example of it's usage: https://github.com/nodejs/node-addon-api/issues/432 – bmacnaughton Jul 08 '19 at 14:42
  • 1
    Thank you very much for your support @bmacnaughton! I've looked precisely inside Napi::FunctionReference and finally found what I was doing wrong! It is not eligible to use the same `value` from the addon method other than that it was introduced in. Instead napi_get_reference_value should be used to extract the corresponded value. – Alexey Ilyushin Jul 11 '19 at 11:15

1 Answers1

2

I've finally found what I was doing wrong. It is not eligible to store g_Value between calls. Instead napi_ref should be stored and napi_get_reference_value function used in order to extract the corresponded value. So the C++ side code should look like this:

// Initialize method:
napi_ref ref;
napi_create_reference(env, value, 1, &ref);
g_Ref = ref; // store the reference somewhere between calls

// MyAddonMethod method:
napi_value referenceValue;
napi_get_reference_value(env, g_Ref, &referenceValue);
napi_valuetype type;
napi_status stat = napi_typeof(env, referenceValue, &type); // napi_ok, napi_function

Of course you should not forget to release the reference using napi_delete_reference when it is not needed anymore.