将duktape 2.1.0中的本地C模块加载到
在阅读how-to文章后,我仍然迷失了方向。
- https://github.com/svaarala/duktape/tree/master/extras/module-node
据说
负载callback函数是一个Duktape / C函数,它使用已parsing的模块ID,并且:(1)返回模块的Ecmascript源代码,或者如果没有源代码,则返回undefined,例如纯C模块;(2)可以填充module.exports本身,(3)可以取代module.exports。
但是当加载一个本地C模块时,
- 什么应该推入价值栈?
duk_push_undefined(ctx)
而不是duk_push_string(ctx, module_source)
? - 负载callback应该返回给调用者的是什么?
return 0
而不是return 1
?
我试图在loadcallbackcb_load_module
调用myobject_init
(使用http://wiki.duktape.org/HowtoNativeConstructor.html中的默认实例)。 但是duktape抱怨
TypeError:[对象对象]不可构造
当我评估var MyObject = require("MyObject")
,无论如何
- 将undefined push到值栈中并返回1,
- 或者将任何东西压入值栈并返回0。
问题解决了。 还有更多的细节散落在其中
- https://github.com/svaarala/duktape/blob/master/doc/c-module-convention.rst
- http://wiki.duktape.org/HowtoModules.html这是关于duktape 1.x模块加载框架,但它有助于理解2.x框架。
最重要的技巧是:
-
模块init函数应该返回一个函数(构造函数也是一个函数)。 不要使用
duk_put_global_string
注册函数。duk_ret_t module_init(duk_context* ctx) { duk_push_c_function(ctx, module_constructor, num_arguments_for_constructor); // set properties for the constructor return 1; // stack: [ ... constructor ] }
-
函数
cb_load_module
必须将模块初始化函数推入值栈,然后使用duk_call
调用它并设置module.exports
。 不要直接调用模块初始化函数。duk_ret_t cb_load_module(duk_context *ctx) { // stack: [ resolved_id exports module ] ... duk_push_c_function(ctx, module_init, 0); duk_call(ctx, 0); duk_put_prop_string(ctx, 2, "exports"); // obj_idx(module) = 2 return 0; // no .js source for native modules }