首页 > 解决方案 > emscripten_sleep_with_yield() 期间的非解释调用

问题描述

我有一个通过Emscripten emterpreter转换为 Javascript 的 C 例程,它调用emscripten_sleep_with_yield(). 虽然它正在产生,但我想在异步回调中运行一些非解释的 C 代码。当我尝试时,有一条错误消息显示:

“此错误发生在 emterpreter-async 保存或加载堆栈期间。保存期间堆栈上是否有非 emterpreted 代码(这是不允许的)?”

从抽象的意义上说,我不确定为什么在堆栈加载或保存时调用非空解析代码会有任何问题——它实际上并不被要求保留的堆栈上。

这个非解释代码的动机是更新一些对产生的例程可见的结构。我发现回调中的纯 JavaScript 在技术上可以通过setValue()进入 emscripten 堆来实现影响。但是通过 JavaScript 进行 C 操作是很尴尬的,特别是因为许多例程,比如底层AllocateUTF8()调用_malloc()……而且这些例程都有同样的问题。

这是一个显示问题的简单示例。有没有办法解决这个问题......例如,在进行非解释调用时将加载/保存状态变量存储在某处,然后将它们放回去?

测试.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Plain call during Emterpreter Stack Load</title>
    <script src="test.o.js"></script>
    <script>
      Module.onRuntimeInitialized = function() {
        setTimeout(function () {
          console.log("calling not_emterpreted()");
          _not_emterpreted();
        }, 0);
        _emterpreted_yielder();
        console.log("yielding...");
      }
    </script>
  </head>
  <body></body>
</html>

测试.c

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

EMSCRIPTEN_KEEPALIVE void emterpreted_yielder() {
    while (1) {
        printf("emterpreted_yielder() sleeping...\n");
        emscripten_sleep_with_yield(1000);
    }
}

EMSCRIPTEN_KEEPALIVE void not_emterpreted() {
    printf("Entering not_emterpreted()\n");
}

构建:

emcc test.c -o test.o.js -s EMTERPRETIFY=1 -s EMTERPRETIFY_ASYNC=1 -s EMTERPRETIFY_BLACKLIST="['_not_emterpreted']"

注释掉not_emterpreted()html 中的调用将导致它执行预期的睡眠循环。就像我说的那样,那时您可以将 C 影响作为针对 emterpreter 堆的原始 JavaScript 指令。但是......这不是非解释的emscripten C吗?:-/

标签: emscripten

解决方案


这是 emscripten 中过于保守的错误机制。针对这个问题,现在已经取消了限制:

https://github.com/kripken/emscripten/pull/6822


推荐阅读