4

我正在使用 Duktape 嵌入 JavaScript,但使用require总是会导致错误:

int main(){
  duk_context *ctx = duk_create_heap_default();
  duk_peval_file(ctx, "example.js");
  printf("file load err %s", duk_safe_to_string(ctx, -1));
  duk_destroy_heap(ctx);
}

例子.js

var mylib = require("mylib")
print (mylib.hello)

mylib.js

exports.hello = "Hello"

错误:

文件加载错误类型错误:不可调用

堆栈转储 说:

duk_js_call.c:682
需要原生严格preventyield
eval example.js:1 preventyield

4

2 回答 2

5

Duktape 要求(不是双关语)您提供模块搜索功能以保持可移植性。但是,即使您对 Duktape 没有什么经验,实现一个也是一项非常简单直接的任务。
一个非常简单但功能齐全的模块搜索功能是:

Duktape.modSearch = function(id) {
    return readFileAsString(id);
}

这将允许您使用文件名require(filename)作为参数从 Duktape Javascript 环境中调用并将其用作您的模块。更高级的功能将处理错误或搜索多个路径和文件夹。

要使用该require()函数,您现在必须创建一个 C/C++ 函数来处理读取文件并将其内容作为字符串返回并将该函数绑定到 Duktape 引擎(此示例位于Duktape主页上)。
现在从 Duktape 运行时调用这个函数定义(例如使用duk_eval_string(ctx, "Duktape.modSearch = ...");),你应该能够调用require().

于 2015-03-14T23:03:22.760 回答
0

这个答案相当不完整。把很多事情留给想象。

以下代码不是我的,但在 sof 中也有,解决了实现 modSearch 功能的问题:

duk_ret_t mod_search(duk_context *ctx) {
    /* Nargs was given as 4 and we get the following stack arguments:
     *   index 0: id
     *   index 1: require
     *   index 2: exports
     *   index 3: module
     */
char *src = NULL;
FILE *f   = NULL;
const char *filename = "/home/user/benchmark/js_modules/mylib.js";

int  rc, len;

// Pull Arguments
char *id = duk_require_string(ctx, 0);

printf("ID => %s \n", id);

rc = strcmp(id, "mylib");
if(rc == 0)
{
    printf("Module found, loading... \n");
    // Read File and calculate its size (as DUKtape examples)
    f = fopen(filename, "rb");
    fseek(f, 0, SEEK_END);
    len = (int) ftell(f);

    // Rewind
    fseek(f, 0, SEEK_SET);

    src = malloc(len);
    fread(src, 1, len,f);
    fclose(f);
    duk_push_lstring(ctx, src, len);
    free(src);
    return 1;
  }
// Error
    return -1;
}

然后,我们需要一个本地代码 C 函数来注册 modSearch 函数:

/* Declaration */
void modSearch_register(duk_context *ctx) {
    duk_get_global_string(ctx, "Duktape");
    duk_push_c_function(ctx, mod_search, 4 /*nargs*/);
    duk_put_prop_string(ctx, -2, "modSearch");
    duk_pop(ctx);
}

然后是主要代码:

duk_context *ctx;

ctx = duk_create_heap_default();
if (!ctx) {
    return 1;
}
duk_push_c_function(ctx, handle_print, 1);
duk_put_global_string(ctx, "print");
duk_module_duktape_init(ctx);
printf("top after init: %ld\n", (long) duk_get_top(ctx));
//call function defintion for require
modSearch_register(ctx);

/* We push to Duktape heap the JS file*/
push_file_as_string(ctx, argv[1]);
if (duk_peval(ctx) != 0) {
    printf("Error peval: %s\n", duk_safe_to_string(ctx, -1));
        goto finished;
    }
duk_pop(ctx);  /* pop result/error */

finished:
duk_destroy_heap(ctx);

可以从 duktape 网页获取原生 c 代码打印功能,例如:

static duk_ret_t handle_print(duk_context *ctx) {
    printf("%s\n", duk_safe_to_string(ctx, 0));
    return 0;
}
于 2019-07-19T16:08:52.807 回答