4

嗨所以我在看 duktape,但我似乎找不到一个简单的例子来做类似的事情:

  • 预编译一些js。
  • 传递该 js 一些输入,例如字符串和数字并运行它。
  • 得到那个js的结果。

似乎示例从这里是如何评估 js 到这里是如何从 js 调用 C 函数,也许我错过了。

好吧,在抨击 API 文档和反复试验之后,我最终得到了类似的东西:

duk_context *ctx = duk_create_heap_default();

duk_eval_string(ctx, "(function helloWorld(a,b) { return a.includes(b); })");    
duk_dump_function(ctx);

int i;
for(i = 0; i < 10; i++) {
  duk_dup_top(ctx); // I don't know why but it seems needed
  duk_load_function(ctx);  /* [ ... bytecode ] -> [ ... function ] */
  duk_push_string(ctx, "the");
  duk_push_string(ctx, "th");
  duk_call(ctx, 2);
  
  duk_bool_t res = duk_get_boolean(ctx, -1);
  if(res) {
    printf("You got it!\n");
  } else {
    printf("yeah nah!\n");
  }
  duk_pop(ctx);
}

虽然我注意到如果 JS 有错误我得到一个段错误,也许我应该检查一些东西?

这也是缓存JS的正确方法吗?

4

1 回答 1

3

好的,这是一个基于我正在工作的代码拼凑而成的片段,它应该做一些类似于你的例子的事情

bool compileJS(duk_context *ctx, const char* programBody)
{
  bool success = false;

  // Compile the JS into bytecode
  if (duk_pcompile_string(ctx, 0, programBody) != 0)
  {
    // Error in program code

    printf("Compile failed\n");
    printf("%s\n", duk_safe_to_string(ctx, -1));
  }
  else
  {
    // Actually evaluate it - this will push the compiled code into the global scope
    duk_pcall(ctx, 0);

    success = true;

  }
  duk_pop(ctx);

  return success;
}

duk_bool_t runJSFunction(duk_context *ctx, const char* funcName, const char* arga, const char* argb)
{
  duk_bool_t returnVal;

  // Get a reference to the named JS function
  if (duk_get_global_string(ctx, funcName))
  {
    // Function found, push the args

    duk_push_string(ctx, arga);
    duk_push_string(ctx, argb);

    // Use pcall - this lets you catch and handle any errors
    if (duk_pcall(ctx, 2) != DUK_EXEC_SUCCESS)
    {
      // An error occurred - display a stack trace
      duk_get_prop_string(ctx, -1, "stack");
      printf(duk_safe_to_string(ctx, -1));
    }
    else
    {
      // function executed successfully - get result
      returnVal = duk_get_boolean(ctx, -1);
    }
  }
  else
  {
    printf("JS function not found!\n");
    returnVal = false;
  }

  duk_pop(ctx); // pop result

  return returnVal;
}

void testJS()
{
  duk_context *ctx = duk_create_heap_default();

  const char* programBody = "function helloWorld(a,b) { return a.includes(b); }";

  if (compileJS(ctx, programBody))
  {
    for (int i = 0; i < 10; ++i)
    {
      bool ret = runJSFunction(ctx, "helloWorld", "the", "th");
      if (ret)
      {
        printf("You got it!\n");
      }
      else
      {
        printf("yeah nah!\n");
      }
    }
  }
}

我把它分成三个函数,这样你就可以看到函数的初始化和编译(以及缓存)是如何与 JS 执行分开处理的。我还添加了基本的错误处理,如果您的 JS 代码无法编译或运行,它应该会显示错误。

于 2018-04-14T18:41:33.790 回答