1.对象封装
#include "myobject.h"
#include <assert.h>
napi_ref MyObject::constructor;
MyObject::MyObject(double value)
: value_(value), env_(nullptr), wrapper_(nullptr) {}
//4. 析构函数,解除持久化引用
MyObject::~MyObject() { napi_delete_reference(env_, wrapper_); }
// 3. Js对象销毁时,调用的方法
void MyObject::Destructor(napi_env env, void* nativeObject, void* /*finalize_hint*/) {
reinterpret_cast<MyObject*>(nativeObject)->~MyObject();
}
#define DECLARE_NAPI_METHOD(name, func) \
{ name, 0, func, 0, 0, 0, napi_default, 0 }
//1.该静态方法在js进行require操作时,调用
napi_value MyObject::Init(napi_env env, napi_value exports) {
napi_status status;
//定义对象的方法和参数对象
napi_property_descriptor properties[] = {
{ "value", 0, 0, GetValue, SetValue, 0, napi_default, 0 },
DECLARE_NAPI_METHOD("plusOne", PlusOne),
DECLARE_NAPI_METHOD("multiply", Multiply),
};
napi_value cons;
//创建对象结构
status =
napi_define_class(env, "MyObject", NAPI_AUTO_LENGTH, New, nullptr, 3, properties, &cons);
assert(status == napi_ok);
//通过引用,来对对象结构进行持久化保存
status = napi_create_reference(env, cons, 1, &constructor);
assert(status == napi_ok);
//将对象结构挂载到exports上,对外暴露
status = napi_set_named_property(env, exports, "MyObject", cons);
assert(status == napi_ok);
//返回exports
return exports;
}
//2.该方法在对外暴露的对象结构中的方法被调用时,或者使用对象结构创建一个新的实例时。
napi_value MyObject::New(napi_env env, napi_callback_info info) {
napi_status status;
napi_value target;
//该方法判断是否通过 new target 的方式创建对象
status = napi_get_new_target(env, info, &target);
assert(status == napi_ok);
bool is_constructor = target != nullptr;
if (is_constructor) {
// 以new target 的方式创建实例对象
size_t argc = 1;
napi_value args[1];
napi_value jsthis;
//获取创建时的参数
status = napi_get_cb_info(env, info, &argc, args, &jsthis, nullptr);
assert(status == napi_ok);
double value = 0;
napi_valuetype valuetype;
//判断参数类型
status = napi_typeof(env, args[0], &valuetype);
assert(status == napi_ok);
if (valuetype != napi_undefined) {
status = napi_get_value_double(env, args[0], &value);
assert(status == napi_ok);
}
//创建实例对象
MyObject* obj = new MyObject(value);
obj->env_ = env;
//使用实例后的对象进行封装,封装成js可调用的对象,并使用引用进行持久化保存,这个方法与napi_new_instance 类似, 但是napi_wrap并没有对对象进行执持久化处理, 这也是new target 的区别
status = napi_wrap(env,
jsthis,
reinterpret_cast<void*>(obj), //对象销毁时,调用的方法
MyObject::Destructor,
nullptr, // finalize_hint
&obj->wrapper_);
assert(status == napi_ok);
//返回封装后的实例
return jsthis;
} else {
// 不实例化对象,直接调用对象方法
size_t argc_ = 1;
napi_value args[1];
//获取参数
status = napi_get_cb_info(env, info, &argc_, args, nullptr, nullptr);
assert(status == napi_ok);
const size_t argc = 1;
napi_value argv[argc] = {args[0]};
napi_value cons;
//参数类型判断
status = napi_get_reference_value(env, constructor, &cons);
assert(status == napi_ok);
napi_value instance;
//创建一个零时实例对象
status = napi_new_instance(env, cons, argc, argv, &instance);
assert(status == napi_ok);
// 返回临时的对象,该对象在使用完成后,就立即销毁了
return instance;
}
}
//5. 取值操作
napi_value MyObject::GetValue(napi_env env, napi_callback_info info) {
napi_status status;
napi_value jsthis;
//获取js实例
status = napi_get_cb_info(env, info, nullptr, nullptr, &jsthis, nullptr);
assert(status == napi_ok);
MyObject* obj;
//使用js的实例来获取C++实例对象,
status = napi_unwrap(env, jsthis, reinterpret_cast<void**>(&obj));
assert(status == napi_ok);
napi_value num;
//创建js数据类型
status = napi_create_double(env, obj->value_, &num);
assert(status == napi_ok);
//返回js调用结果
return num;
}
//6. 设置操作
napi_value MyObject::SetValue(napi_env env, napi_callback_info info) {
napi_status status;
size_t argc = 1;
napi_value value;
napi_value jsthis;
status = napi_get_cb_info(env, info, &argc, &value, &jsthis, nullptr);
assert(status == napi_ok);
MyObject* obj;
status = napi_unwrap(env, jsthis, reinterpret_cast<void**>(&obj));
assert(status == napi_ok);
status = napi_get_value_double(env, value, &obj->value_);
assert(status == napi_ok);
return nullptr;
}
//7.递增加1操作
napi_value MyObject::PlusOne(napi_env env, napi_callback_info info) {
napi_status status;
napi_value jsthis;
status = napi_get_cb_info(env, info, nullptr, nullptr, &jsthis, nullptr);
assert(status == napi_ok);
MyObject* obj;
status = napi_unwrap(env, jsthis, reinterpret_cast<void**>(&obj));
assert(status == napi_ok);
obj->value_ += 1;
napi_value num;
status = napi_create_double(env, obj->value_, &num);
assert(status == napi_ok);
return num;
}
//8,该方法直接对value进行操作,而且返回一个零时对象
napi_value MyObject::Multiply(napi_env env, napi_callback_info info) {
napi_status status;
size_t argc = 1;
napi_value args[1];
napi_value jsthis;
status = napi_get_cb_info(env, info, &argc, args, &jsthis, nullptr);
assert(status == napi_ok);
napi_valuetype valuetype;
status = napi_typeof(env, args[0], &valuetype);
assert(status == napi_ok);
double multiple = 1;
if (valuetype != napi_undefined) {
status = napi_get_value_double(env, args[0], &multiple);
assert(status == napi_ok);
}
MyObject* obj;
//使用js实例获取C++实例对象
status = napi_unwrap(env, jsthis, reinterpret_cast<void**>(&obj));
assert(status == napi_ok);
napi_value cons;
//此处挺有意思,使用引用constructor获取对象结构
status = napi_get_reference_value(env, constructor, &cons);
assert(status == napi_ok);
const int kArgCount = 1;
napi_value argv[kArgCount];
//创建js数据类型
status = napi_create_double(env, obj->value_ * multiple, argv);
assert(status == napi_ok);
napi_value instance;
//创建零时js对象
status = napi_new_instance(env, cons, kArgCount, argv, &instance);
assert(status == napi_ok);
//返回创建对象
return instance;
}
使用
var addon = require('bindings')('addon');
var obj = new addon.MyObject(10);
console.log( obj.plusOne() ); // 11
console.log( obj.plusOne() ); // 12
console.log( obj.plusOne() ); // 13
console.log( obj.multiply().value ); // 13
console.log( obj.multiply(10).value ); // 130
var newobj = obj.multiply(-1);
console.log( newobj.value ); // -13
console.log( obj === newobj ); // false
网友评论