在duktape 2.1.0中加载本机C模块

时间:2017-04-29 21:34:04

标签: javascript node.js duktape

在阅读了how-to文章之后,我仍然迷失方向。

据说

  

加载回调是一个Duktape / C函数,它获取已解析的模块ID,并且:(1)返回模块的Ecmascript源代码,如果没有源代码,则返回undefined,例如:对于纯C模块,(2)可以填充module.exports本身,(3)可以替换module.exports。

但是在加载本机C模块时,

  • 什么应该被推入价值堆栈? duk_push_undefined(ctx)代替duk_push_string(ctx, module_source)
  • 加载回调给它的调用者应该返回什么? return 0代替return 1

我尝试在加载回调myobject_init中调用cb_load_module(使用http://wiki.duktape.org/HowtoNativeConstructor.html中的默认实例)。但duktape抱怨

  

TypeError:[object Object]不可构造

当我评估var MyObject = require("MyObject")时,无论我

  • 将undefined推入值堆栈并返回1,
  • 或者什么都不推入值堆栈并返回0。

1 个答案:

答案 0 :(得分:2)

问题解决了。

中还有一些细节

最重要的技巧是:

  • 模块初始化函数应该返回一个函数(构造函数也是一个函数)。请勿使用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必须将模块init函数推入值堆栈,然后使用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
    }