More Related Content
Similar to Node native ext
Similar to Node native ext (20)
Node native ext
- 4. SWIG
Ruby, Python, Javaなんかで使われる、ネイティブ拡張生成のシステム。
独自のインターフェース定義言語から、自動的にGlueCodeを作る。
わりかしいい具合にやってくれるが、複雑なのはやっぱりしんどい。
JavaScriptはコールバック関数に対応していないなど、まだイマイチ
- 7. C言語との接続の設計
簡単な例
const char* hello() { return “hello”; }
これなら、だいたいの言語で文字列をマッピングする機能がある。
Napi::String Function(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
return Napi::String::New(env, hello() );
}
Napi::Object Init(Napi::Env env, Napi::Object exports) {
exports.Set(Napi::String::New(env, “function"),
Napi::Function::New(env, Function));
return exports;
}
Node.js側にhello()をラップした関数オブジェクトを渡すことで、Node.jsからラッパ関数を呼べる。
ラッパ経由でhello()を呼べる
- 8. Node.jsから呼ぶ
var addon = require('native-extension');
console.log(addon.function());
function() Function() hello()
- 11. Node.jsから呼び出す
var obj = new addon.MyObject();
console.log( obj.plusOne() );
new
MyObject()
Constructor
obj.
plusOne()
PlusOne()
- 14. Node.jsから呼び出す
var addon = require('native-extension');
console.log(addon.function_ext());
function_ext() FunctionExt
External mem
Externalは単なるプレースホルダ 中身はみせられない
- 15. 困るやつ(ネストされたclass,struct)
struct inner_t {int x; int y}
struct outer_t { struct inner_t inner_x; int z; }
Int func(struct inner_t* sx) {…}
struct Outer の中身のstruct Innerを取り出して使うパターン。
ラッパオブジェクト Inner のコンストラクタを呼べるようにしておく。
Externalでやると、中身が操作できないので困る。
- 16. Napi::Function Inner::GetClass(Napi::Env env) {
Napi::Function func = DefineClass(…);
constructor = Napi::Persistent(func);
constructor.SuppressDestruct();
}
Napi::Object Outer::get_inner_x(…) {
return Inner::constructor.new({});
}
Outerのラッパでinner_xを参照したときに、Innerのラッパオブジェクトを作
る。
- 17. var obj = new addon.MyObject();
console.log( obj.plusOne() );
new
MyObject()
Outer
obj.
Inner
get_inner
Inner.x Inner::get_x
Inner
Constructor
- 20. var obj = new addon.MyObject();
console.log( obj.inner );
console.log( new Inner() );
new
MyObject()
Constructor
obj.
Inner
get_inner
Inner
Constructor
New
Inner()
Inner
Constructor
- 21. 多分これでいいはず…?
//コンストラクタの引数ありなしでメモリを使い分ける
Inner::Inner(const Napi::CallbackInfo& info) : ObjectWrap(info)
{
if (info.Length() == 0) {
/* 自力で作るパターン。自前でメモリ*/
m_shptr = make_shared<struct inner_t>();
}
else if (info.Length() == 1 && info[0].IsExternal() ) {
/* 外からもらったshared_ptrを弱参照する (使わなくなったら消える)。*/
m_shptr = info[0].As<Napi::External< shared _ptr<struct inner_t> >();
}
else { /* 例外 */ }
}
- 22. var non_deletable_inner = obj.inner_x; //objがいる限り中身は消さない
var deletable_x = new Inner(); // gcする
ネイティブ内部でもうまくライフサイクルの管理が必要
だいたいC++のshared_ptrでいけるはず。