I have a C++ class wrapped in Napi::ObjectWrap<> as usual.
I need to call a wrapper member function from another wrapper member. Is this possible? How to construct the Napi::CallbackInfo object to hold a given set of parameters?
myobject.h
#ifndef MYOBJECT_H
#define MYOBJECT_H
#include <napi.h>
class MyObject : public Napi::ObjectWrap<MyObject>
{
public:
static Napi::Object Init(Napi::Env env, Napi::Object exports)
{
Napi::Function func = DefineClass(env, "MyObject", {
InstanceMethod("getter", &MyObject::getter),
InstanceMethod("setter", &MyObject::setter),
InstanceMethod("fromJSON", &MyObject::fromJSON)});
constructor = Napi::Persistent(func);
constructor.SuppressDestruct();
exports.Set("MyObject", func);
return exports;
}
MyObject(const Napi::CallbackInfo &info) : Napi::ObjectWrap<MyObject>(info) {}
private:
static Napi::FunctionReference constructor;
Napi::Value getter(const Napi::CallbackInfo &info)
{
return Napi::Number::New(info.Env(), this->value_);
}
void setter(const Napi::CallbackInfo &info)
{
this->value_ = info[0].ToNumber();
}
void fromJSON(const Napi::CallbackInfo &info)
{
/**
* obj = {
* val1: 99.44,
* val2: 3.14
* }
*/
auto obj = info[0].ToObject();
double val1 = obj.Get("val1").ToNumber(); // don't care
double val2 = obj.Get("val2").ToNumber();
// setter(val2); // Shall set this->value_ to value of obj.val2
/**
* How to call setter() with appropriate Napi::CallbackInfo object that contains only 'obj.Get("val2")' as first parameter?
*/
}
double value_ = 0.0;
};
Napi::FunctionReference MyObject::constructor;
#endif
addon.js
var addon = require("bindings")("addon");
var obj = new addon.MyObject(42.0);
console.log(obj.getter());
console.log(obj.setter(45.6));
console.log(obj.fromJSON({
val1: 99.44,
val2: 3.14
}));
Here, I want to call setter(const Napi::CallbackInfo &info) from void fromJSON(const Napi::CallbackInfo &info).
Thank you for your advices.
Someone with a little more N-API experience can chime in, but I've just avoided the issue by using those methods as my interface and just using private methods to do the actual work. The private methods can take any arguments I want/need without needing the complexities of JavaScript callbacks.
I would also say, that the setter is a callback. If you need to reuse its implementation, then extract it and define like
void SetterCallback(const CallbackInfo& info) {
Setter(info[0].ToNumber().DoubleValue());
}
void Setter(double value) {
value_ = value;
}
I think the idea is not to create your own CallbackInfo.
+1 to the suggestions to avoid trying to build CallbackInfo, having extracted methods that you can use both from native and in the callbacks. The other advantage is that it will be more performant because it avoids crossing the JavaScript/Native barrier to create JS objects.
Thank you all for the suggestions. I have made it using an extracted function.
Most helpful comment
Someone with a little more N-API experience can chime in, but I've just avoided the issue by using those methods as my interface and just using private methods to do the actual work. The private methods can take any arguments I want/need without needing the complexities of JavaScript callbacks.