1

阅读操作方法文章后,我仍然迷失了方向。

据说

加载回调是一个 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(使用http://wiki.duktape.org/HowtoNativeConstructor.htmlcb_load_module中的默认实例) 。但 duktape 抱怨

TypeError:[object Object] 不可构造

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

  • 将 undefined 压入值栈并返回 1,
  • 或不向值堆栈中压入任何内容并返回 0。
4

1 回答 1

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必须将模块初始化函数推入值堆栈,然后用于duk_call调用它并设置module.exports。不要直接调用模块的 init 函数。

    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
    }
    
于 2017-04-30T19:58:40.890 回答