来自 C 代码的异步 javascript 库调用完成得太晚

Posted

技术标签:

【中文标题】来自 C 代码的异步 javascript 库调用完成得太晚【英文标题】:async javascript library call from C code finishes too late 【发布时间】:2017-02-12 09:23:28 【问题描述】:

我正在使用 emscripten 编译一个使用我编写的 javascript 库的 C 程序,并将它们与 --js-library 标志链接在一起。我的 C 代码调用库中的一个函数,其中有一个 Promise,并且在回调中我希望它把给定的结果写入一些内存,该内存已经从 C 调用者传递给 JS 函数。这是一个示例(为简洁起见,我省略了 Promise 中捕获错误的 catch 部分):

lib.js

mergeInto(LibraryManager.library, 
  compute_js: function(input, out_buf) 
    do_promise_computation(
      input
    ).then(function(result)
       Module.print("Promise Returned fully");
       for (var i = 0; i < 8; i++) 
         var num = result[i]
         makeSetValue('out_buf+(i*4)', 0, 'num', 'i32')
       
  );

程序.c

#include <stdio.h>
#include <stdint.h>
#include <emscripten.h>

extern void compute_js(int32_t, int64_t*);

int main() 
  int32_t input = 1234;
  int64_t out_buf[4];
  int64_t* out_ptr = (int64_t*)(&out_buf);
  printf("Calling Javascript\n");
  compute_js(input, out_ptr);
  printf("%lld\n", out_buf[0]);
  printf("%lld\n", out_buf[1]);

在我为库编写的没有 Promises 的其他函数中,我已经能够成功地将数据写入 C 代码给定的缓冲区,但是这一次,输出返回如下:

Calling Javascript
0
0
Promise Returned fully

但我希望能够等待 Promise 的结果,然后将其写入 C 代码,以便 Promise Returned Fully 出现在 JavaScript 调用之后的 C 代码中的 printf 语句之前。有没有办法用 emscripten 做到这一点?

【问题讨论】:

emscripten 恐怕我不太熟悉,但是我的一个朋友被问到是否可以使用信号量,它应该可以解决您的问题。 我不知道这个环境,但是你可以让你的 Javascript 在你的 C 代码中从 .then() 处理程序调用一个回调函数吗? 【参考方案1】:

使用ASYNCIFY_FUNCTIONS_emscripten_async_resume

https://kripken.github.io/emscripten-site/docs/porting/asyncify.html

【讨论】:

我试过这个,但即使按照所说的做了,我还是会出错。也就是说,我不确定在哪里打电话给_emscripten_async_resume()。如果我在 C 中调用它,它会说它是一个函数的“隐式声明”并且不允许。如果我在 JS 中调用它,我会被告知 ReferenceError: ___async is not defined。我一直在用-s ASYNCIFy=1 -s ASINCIFY_FUNCTIONS=['compute_js_helper'] 编译我的代码(帮助函数是一个包装了JS函数调用的C函数)。

以上是关于来自 C 代码的异步 javascript 库调用完成得太晚的主要内容,如果未能解决你的问题,请参考以下文章

使用来自 javascript 的 const *const *inputs 调用 C webassembly 函数

javascript异步编程学习及实例

C#有异步函数调用同步函数或同步函数调用异步函数

JavaScript ES6 类是不是可用于异步代码库?

从小小题目逐步走进 JavaScript 异步调用

#打卡不停更#三方库移植之NAPI开发[4]异步调用:Callback&Promise