emscripten.h

本页面介绍了 emscripten.h 提供的公共 C++ API。

Emscripten 尽可能使用现有的/熟悉的 API(例如:SDL)。此 API 为特定于 JavaScript 或浏览器环境或没有现有 API 的功能提供了 C++ 支持。

内联汇编/JavaScript

以下 API 的指南材料可以在 从 C/C++ 调用 JavaScript 中找到。

定义

EM_JS(return_type, function_name, arguments, code)

用于 JavaScript 库函数的便捷语法。

这允许您在 C 代码中将 JavaScript 声明为函数,该函数可以像普通 C 函数一样调用。例如,以下 C 程序如果用 Emscripten 编译并在浏览器中运行,将显示两个警报

EM_JS(void, two_alerts, (), {
  alert('hai');
  alert('bai');
});

int main() {
  two_alerts();
  return 0;
}

参数可以像普通 C 参数一样传递,并且在 JavaScript 代码中具有相同的名称。这些参数可以是 int32_tdouble 类型。

EM_JS(void, take_args, (int x, float y), {
  console.log('I received: ' + [x, y]);
});

int main() {
  take_args(100, 35.5);
  return 0;
}

以 null 结尾的 C 字符串也可以传递到 EM_JS 函数中,但要对它们进行操作,需要将它们从堆中复制出来以转换为高级 JavaScript 字符串。

EM_JS(void, say_hello, (const char* str), {
  console.log('hello ' + UTF8ToString(str));
}

以相同的方式,可以将指向任何类型(包括 void *)的指针传递到 EM_JS 代码中,它们在那里显示为整数,就像上面的 char * 指针一样。可以通过直接读取堆来管理对数据的访问。

EM_JS(void, read_data, (int* data), {
  console.log('Data: ' + HEAP32[data>>2] + ', ' + HEAP32[(data+4)>>2]);
});

int main() {
  int arr[2] = { 30, 45 };
  read_data(arr);
  return 0;
}

此外,EM_JS 函数可以将值返回给 C 代码。输出值使用 return 语句传回

EM_JS(int, add_forty_two, (int n), {
  return n + 42;
});

EM_JS(int, get_memory_size, (), {
  return HEAP8.length;
});

int main() {
  int x = add_forty_two(100);
  int y = get_memory_size();
  // ...
}

字符串可以从 JavaScript 返回到 C,但需要小心内存管理。

EM_JS(char*, get_unicode_str, (), {
  var jsString = 'Hello with some exotic Unicode characters: Tässä on yksi lumiukko: ☃, ole hyvä.';
  // 'jsString.length' would return the length of the string as UTF-16
  // units, but Emscripten C strings operate as UTF-8.
  return stringToNewUTF8(jsString);
});

int main() {
  char* str = get_unicode_str();
  printf("UTF8 string says: %s\n", str);
  // Each call to _malloc() must be paired with free(), or heap memory will leak!
  free(str);
  return 0;
}
EM_ASM(...)

用于内联汇编/JavaScript 的便捷语法。

这允许您在 C 代码中“内联”声明 JavaScript,然后在编译后的代码在浏览器中运行时执行它。例如,以下 C 代码如果用 Emscripten 编译并在浏览器中运行,将显示两个警报

EM_ASM(alert('hai'); alert('bai'));

参数可以传递到 JavaScript 代码块中,它们在那里作为变量 $0$1 等出现。这些参数可以是 int32_tdouble 类型。

EM_ASM({
  console.log('I received: ' + [$0, $1]);
}, 100, 35.5);

请注意 {}

以 null 结尾的 C 字符串也可以传递到 EM_ASM 块中,但要对它们进行操作,需要将它们从堆中复制出来以转换为高级 JavaScript 字符串。

EM_ASM(console.log('hello ' + UTF8ToString($0)), "world!");

以相同的方式,可以将指向任何类型(包括 void *)的指针传递到 EM_ASM 代码中,它们在那里显示为整数,就像上面的 char * 指针一样。可以通过直接读取堆来管理对数据的访问。

int arr[2] = { 30, 45 };
EM_ASM({
  console.log('Data: ' + HEAP32[$0>>2] + ', ' + HEAP32[($0+4)>>2]);
}, arr);

注意

  • 从 Emscripten 1.30.4 开始,EM_ASM 代码块的内容出现在正常的 JS 文件中,因此 Closure 编译器和其他 JavaScript 缩减器将能够对它们进行操作。您可能需要在某些地方使用安全引号 (a['b'] 而不是 a.b) 以避免缩减发生。

  • C 预处理器不了解 JavaScript 令牌,因此如果 code 块包含逗号字符 ,,则可能需要将代码块括在圆括号中。例如,代码 EM_ASM(return [1,2,3].length); 无法编译,但 EM_ASM((return [1,2,3].length)); 可以。

EM_ASM_INT(code, ...)

此宏以及 EM_ASM_DOUBLEEM_ASM_PTR 的行为类似于 EM_ASM,但此外它们还将值返回给 C 代码。输出值使用 return 语句传回

int x = EM_ASM_INT({
  return $0 + 42;
}, 100);

int y = EM_ASM_INT(return HEAP8.length);
EM_ASM_PTR(code, ...)

类似于 EM_ASM_INT,但用于指针大小的返回值。当使用 -sMEMORY64 构建时,这将导致 i64 返回值,否则将导致 i32 返回值。

字符串可以从 JavaScript 返回到 C,但需要小心内存管理。

char *str = (char*)EM_ASM_PTR({
  var jsString = 'Hello with some exotic Unicode characters: Tässä on yksi lumiukko: ☃, ole hyvä.';
  var lengthBytes = lengthBytesUTF8(jsString)+1;
  // 'jsString.length' would return the length of the string as UTF-16
  // units, but Emscripten C strings operate as UTF-8.
  return stringToNewUTF8(jsString);
});
printf("UTF8 string says: %s\n", str);
free(str); // Each call to _malloc() must be paired with free(), or heap memory will leak!
EM_ASM_DOUBLE(code, ...)

类似于 EM_ASM_INT,但用于 double 返回值。

MAIN_THREAD_EM_ASM(code, ...)

此宏的行为类似于 EM_ASM,但它在主线程上执行调用。这在 pthreads 构建中很有用,当您想要从 pthread 与 DOM 交互时;这基本上为您代理了调用。

此调用以同步方式代理到主线程,也就是说,执行将在主线程完成运行 JS 后恢复。同步代理也使返回值成为可能,请参见接下来的两个变体。

MAIN_THREAD_EM_ASM_INT(code, ...)

类似于 MAIN_THREAD_EM_ASM,但返回一个 int 值。

MAIN_THREAD_EM_ASM_DOUBLE(code, ...)

类似于 MAIN_THREAD_EM_ASM,但返回一个 double 值。

MAIN_THREAD_EM_ASM_PTR(code, ...)

类似于 MAIN_THREAD_EM_ASM,但返回一个指针值。

MAIN_THREAD_ASYNC_EM_ASM(code, ...)

类似于 MAIN_THREAD_EM_ASM,但以 **异步** 方式代理,也就是说,主线程将收到一个请求来运行代码,并且将在它可以的时候运行它;工作线程不会等待。 (请注意,如果在主线程上调用它,则没有任何内容需要代理,并且 JS 会立即同步执行。)

从 C/C++ 调用 JavaScript

以下 API 的指南材料可以在 从 C/C++ 调用 JavaScript 中找到。

回调的函数指针类型

以下类型用于定义在本文件中的许多函数中使用的函数回调签名。

em_callback_func

用于没有参数的回调的通用函数指针类型。

定义为

typedef void (*em_callback_func)(void)
em_arg_callback_func

用于具有单个 void* 参数的回调的通用函数指针类型。

此类型用于定义需要传递任意数据的函数回调。例如,emscripten_set_main_loop_arg() 设置用户定义的数据,并在完成时将其传递给此类型的回调。

定义为

typedef void (*em_arg_callback_func)(void*)
em_str_callback_func

用于回调的通用函数指针类型,带有 C 字符串 (const char *) 参数。

此类型用于需要传递 C 字符串的函数回调。例如,它在 emscripten_async_wget() 中用于传递已异步加载的文件的名称。

定义为

typedef void (*em_str_callback_func)(const char *)

函数

void emscripten_run_script(const char *script)

与底层 JavaScript 引擎的接口。此函数将 eval() 给定的脚本。注意:如果设置了 -sDYNAMIC_EXECUTION=0,则此函数将不可用。

此函数可以从 pthread 中调用,它在托管 pthread 的 Web Worker 的范围内执行。要评估主运行时线程范围内的函数,请参阅函数 emscripten_sync_run_in_main_runtime_thread()。

参数
  • script (const char*) – 要评估的脚本。

返回值类型

void

int emscripten_run_script_int(const char *script)

与底层 JavaScript 引擎的接口。此函数将 eval() 给定的脚本。注意:如果设置了 -sDYNAMIC_EXECUTION=0,则此函数将不可用。

此函数可以从 pthread 中调用,它在托管 pthread 的 Web Worker 的范围内执行。要评估主运行时线程范围内的函数,请参阅函数 emscripten_sync_run_in_main_runtime_thread()。

参数
  • script (const char*) – 要评估的脚本。

返回值

评估结果,作为整数。

返回值类型

int

char *emscripten_run_script_string(const char *script)

与底层 JavaScript 引擎的接口。此函数将 eval() 给定的脚本。请注意,此重载使用跨调用共享的单个缓冲区。注意:如果设置了 -sDYNAMIC_EXECUTION=0,则此函数将不可用。

此函数可以从 pthread 中调用,它在托管 pthread 的 Web Worker 的范围内执行。要评估主运行时线程范围内的函数,请参阅函数 emscripten_sync_run_in_main_runtime_thread()。

参数
  • script (const char*) – 要评估的脚本。

返回值

评估结果,作为字符串。

返回值类型

char*

void emscripten_async_run_script(const char *script, int millis)

异步运行脚本,在指定的时间段后。

此函数可以从 pthread 中调用,它在托管 pthread 的 Web Worker 的范围内执行。要评估主运行时线程范围内的函数,请参阅函数 emscripten_sync_run_in_main_runtime_thread()。

参数
  • script (const char*) – 要评估的脚本。

  • millis (int) – 运行脚本之前的时间,以毫秒为单位。

返回值类型

void

void emscripten_async_load_script(const char *script, em_callback_func onload, em_callback_func onerror)

从 URL 异步加载脚本。

这与运行依赖项系统集成,因此您的脚本可以多次调用 addRunDependency,准备各种异步任务,并在其上调用 removeRunDependency;当所有任务都完成后(或者最初没有运行依赖项),将调用 onload。这在加载资产模块(即文件打包器的输出)时很有用。

此函数当前仅在主浏览器线程中可用,如果在 pthread 中调用,它将立即失败并调用提供的 onerror() 处理程序。

参数
  • script (const char*) – 要评估的脚本。

  • onload (em_callback_func) – 一个回调函数,没有参数,在脚本完全加载后执行。

  • onerror (em_callback_func) – 一个回调函数,没有参数,如果加载时发生错误,则执行。

返回值类型

void

浏览器执行环境

以下 API 的指南材料可以在 Emscripten 运行时环境 中找到。

函数

void emscripten_set_main_loop(em_callback_func func, int fps, bool simulate_infinite_loop)

将 C 函数设置为调用线程的主事件循环。

如果主循环函数需要接收用户定义的数据,请使用 emscripten_set_main_loop_arg() 代替。

JavaScript 环境将以指定的每秒帧数调用该函数。如果在主浏览器线程中调用,将 0 或负值作为 fps 将使用浏览器的 requestAnimationFrame 机制来调用主循环函数。如果正在进行渲染,强烈建议这样做,因为浏览器的 requestAnimationFrame 将确保以适当的平滑速率进行渲染,该速率与浏览器和显示器同步。如果应用程序根本没有进行渲染,则应选择一个适合代码的特定帧速率。

如果 simulate_infinite_loop 为真,则函数将抛出一个异常以停止调用者的执行。这将导致进入主循环而不是运行 emscripten_set_main_loop() 调用后的代码,这是我们最接近模拟无限循环的方式(我们在 glutMainLoop 中的 GLUT 中做了类似的事情)。如果此参数为 false,则行为与添加此参数之前相同,即执行照常继续。请注意,在这两种情况下,我们都不会运行全局析构函数、atexit 等,因为我们知道主循环仍在运行,但如果我们不模拟无限循环,则堆栈将被展开。这意味着,如果 simulate_infinite_loopfalse,并且在堆栈上创建了一个对象,它将在主循环首次被调用之前被清理。

此函数可以在 pthread 中调用,在这种情况下,回调循环将设置为在调用线程的上下文中调用。为了使循环正常工作,调用线程必须通过退出其 pthread 主函数定期“返回”给浏览器,因为只有当调用线程没有执行任何其他代码时,回调才能执行。这意味着运行同步阻塞主循环与 emscripten_set_main_loop() 函数不兼容。

由于 requestAnimationFrame() API 在 Web Worker 中不可用,因此在使用 fps <= 0 在 pthread 中调用 emscripten_set_main_loop() 时,会模拟与显示器刷新率同步的效果,通常不会精确地与垂直同步间隔对齐。

提示

每个线程一次只能有一个主循环函数。要更改主循环函数,首先取消 当前循环,然后调用此函数以设置另一个循环。

注意

请参阅 emscripten_set_main_loop_expected_blockers()emscripten_pause_main_loop()emscripten_resume_main_loop()emscripten_cancel_main_loop(),以了解有关阻塞、暂停和恢复调用线程的主循环的信息。

注意

调用此函数会通过应用参数 fps 指定的计时模式,覆盖调用线程中对 emscripten_set_main_loop_timing() 的任何先前调用的效果。要为当前线程指定不同的计时模式,请在设置主循环后调用函数 emscripten_set_main_loop_timing()

注意

目前,在调用时在堆栈上具有析构函数的对象的 C++ 项目中,使用 新的 Wasm 异常处理simulate_infinite_loop == true 同时使用尚不可行。

参数
  • func (em_callback_func) – 设置为调用线程的主事件循环的 C 函数。

  • fps (int) – JavaScript 调用该函数的每秒帧数。设置 int <=0(推荐)使用浏览器的 requestAnimationFrame 机制来调用该函数。

  • simulate_infinite_loop (bool) – 如果为真,则此函数将抛出一个异常以停止调用者的执行。

void emscripten_set_main_loop_arg(em_arg_callback_func func, void *arg, int fps, bool simulate_infinite_loop)

将 C 函数设置为调用线程的主事件循环,并向其传递用户定义的数据。

另请参见

有关 emscripten_set_main_loop() 中的信息也适用于此函数。

参数
  • func (em_arg_callback_func) – 设置为主事件循环的 C 函数。函数签名必须具有 void* 参数以传递 arg 值。

  • arg (void*) – 传递给主循环函数的用户定义数据,不受 API 本身的干扰。

  • fps (int) – JavaScript 调用该函数的每秒帧数。设置 int <=0(推荐)将使用浏览器的 requestAnimationFrame 机制来调用该函数。

  • simulate_infinite_loop (bool) – 如果为真,则此函数将抛出一个异常以停止调用者的执行。

void emscripten_push_main_loop_blocker(em_arg_callback_func func, void *arg)
void emscripten_push_uncounted_main_loop_blocker(em_arg_callback_func func, void *arg)

添加一个 **阻塞** 调用线程主循环的函数。

该函数将添加到要阻塞的事件队列的末尾;主循环将不会运行,直到队列中的所有阻塞器都完成。

在“计数”版本中,阻塞器会被(内部)计数,并且 Module.setStatus 会被调用,并使用一些文本来报告进度(setStatus 是一个通用钩子,程序可以定义它来显示处理更新)。

注意

  • 主循环阻塞器会阻止主循环运行,并且可以被计数以显示进度。相反,emscripten_async_calls 不会被计数,不会阻止主循环,并且可以在将来的特定时间触发。

参数
  • func (em_arg_callback_func) – 主循环阻塞器函数。函数签名必须有一个 void* 参数,用于传递 arg 值。

  • arg (void*) – 传递给阻塞器函数的用户定义参数。

返回值类型

void

void emscripten_pause_main_loop(void)
void emscripten_resume_main_loop(void)

暂停和恢复调用线程的主循环。

暂停和恢复主循环在您的应用程序需要执行一些同步操作时很有用,例如从网络加载文件。在完成之前运行主循环可能是不正确的(原始代码假设这一点),因此您可以将代码分解为异步回调,但您必须暂停主循环,直到它们完成。

注意

这些是相当底层的函数。 emscripten_push_main_loop_blocker()(及其朋友)提供更便捷的替代方案。

void emscripten_cancel_main_loop(void)

取消调用线程的主事件循环。

另请参阅 emscripten_set_main_loop()emscripten_set_main_loop_arg(),了解有关设置和使用主循环的信息。

注意

此函数会取消主循环,这意味着它将不再被调用。控制流不会发生其他变化。特别是,如果您使用 simulate_infinite_loop 选项启动了主循环,您仍然可以取消主循环,但执行不会在设置主循环后的代码中继续(我们实际上并没有在那里运行无限循环——这在 JavaScript 中是不可能的,因此为了模拟无限循环,我们会在那个阶段停止执行,然后运行的下一件事就是主循环本身,所以看起来像无限循环从那里开始了;取消主循环有点破坏了这个比喻)。

int emscripten_set_main_loop_timing(int mode, int value)

指定调用线程的主循环滴答函数将被调用的调度模式。

此函数可用于交互式控制 Emscripten 运行时驱动由调用函数 emscripten_set_main_loop() 指定的主循环的速率。在原生开发中,这对应于 3D 渲染的“交换间隔”或“呈现间隔”。此函数指定的新的滴答间隔会立即对现有主循环生效,并且此函数只能在通过 emscripten_set_main_loop() 设置主循环后调用。

param int mode

要使用的计时模式。允许的值是 EM_TIMING_SETTIMEOUT、EM_TIMING_RAF 和 EM_TIMING_SETIMMEDIATE。

参数
  • value (int) –

    要为主循环激活的计时值。此值根据 mode 参数进行不同的解释

    • 如果 mode 是 EM_TIMING_SETTIMEOUT,则 value 指定后续滴答到主循环之间等待的毫秒数,并且更新独立于显示器的垂直同步速率(垂直同步关闭)。此方法使用 JavaScript setTimeout 函数来驱动动画。

    • 如果 mode 是 EM_TIMING_RAF,则使用 requestAnimationFrame 函数(启用垂直同步)执行更新,并且此值被解释为主循环的“交换间隔”速率。值 1 指定运行时它应该在每次垂直同步时渲染(通常是 60fps),而值 2 意味着主循环回调应该只在每秒垂直同步时调用(30fps)。作为一般公式,值 n 意味着主循环在每第 n 次垂直同步时更新,或者以 60/n 的速率(对于 60Hz 显示器)和 120/n 的速率(对于 120Hz 显示器)更新。

    • 如果 mode 是 EM_TIMING_SETIMMEDIATE,则使用 setImmediate 函数执行更新,或者如果不可用,则通过 postMessage 模拟。有关更多信息,请参见 setImmediate on MDN <https://mdn.org.cn/en-US/docs/Web/API/Window/setImmediate>。请注意,此模式 **强烈建议不要** 用于将 Emscripten 输出部署到网络,因为它依赖于处于草案状态的不稳定的网络扩展,除 IE 之外的浏览器目前不支持它,并且其实现已被认为在审查中存在争议。

返回值类型

int

返回值

成功时返回 0,失败时返回非零值。如果在调用此函数之前没有活动的主循环,则会发生错误。

注意

浏览器对使用 requestAnimationFrame 进行动画而不是其他提供的模式进行了大量优化。因此,为了获得最佳的跨浏览器体验,使用 mode=EM_TIMING_RAFvalue=1 调用此函数将产生最佳结果。使用 JavaScript setTimeout 函数已知会导致卡顿,并且通常比使用 requestAnimationFrame 函数体验更差。

注意

setTimeoutrequestAnimationFrame 之间存在功能上的差异:如果用户最小化浏览器窗口或隐藏您的应用程序选项卡,浏览器通常会停止调用 requestAnimationFrame 回调,但基于 setTimeout 的主循环将继续运行,尽管间隔会受到严重限制。有关更多信息,请参见 setTimeout on MDN <https://mdn.org.cn/en-US/docs/Web/API/WindowTimers.setTimeout#Inactive_tabs>

void emscripten_get_main_loop_timing(int *mode, int *value)

返回当前生效的主循环计时模式。有关值的解释,请参见函数 emscripten_set_main_loop_timing() 的文档。计时模式由调用函数 emscripten_set_main_loop_timing()emscripten_set_main_loop() 控制。

param mode

如果不为空,则使用的计时模式将在此处返回。

type mode

int*

param value

如果不为空,则使用的计时值将在此处返回。

type value

int*

void emscripten_set_main_loop_expected_blockers(int num)

设置即将推入的阻塞器数量。

该数量用于在主循环继续后报告一组阻塞器的 *相对进度*。

例如,游戏可能需要运行 10 个阻塞器才能开始新关卡。操作将首先将此值设置为 '10',然后推入 10 个阻塞器。当第 3 个阻塞器(比如)完成时,进度将显示为 3/10。

参数
  • num (int) – 即将推入的阻塞器数量。

void emscripten_async_call(em_arg_callback_func func, void *arg, int millis)

异步调用 C 函数,即在将控制权返回给 JavaScript 事件循环后调用。

这是通过 setTimeout 完成的。

在原生构建时,这将变为简单的直接调用,在 SDL_Delay 之后(您必须包含 **SDL.h** 才能使用它)。

如果 millis 为负数,则将使用浏览器的 requestAnimationFrame 机制。(请注意,0 表示仍然使用 setTimeout,这基本上意味着“尽快异步运行”)。

参数
  • func (em_arg_callback_func) – 要异步调用的 C 函数。函数签名必须有一个 void* 参数,用于传递 arg 值。

  • arg (void*) – 传递给 C 函数的用户定义参数。

  • millis (int) – 函数调用前的超时时间。

void emscripten_exit_with_live_runtime(void)

停止当前的执行线程,但保持运行时处于活动状态,以便您稍后继续运行代码(因此不会运行全局析构函数等)。请注意,当您执行异步操作(如 emscripten_async_call())时,运行时会自动保持活动状态,因此在这些情况下不需要调用此函数。

在多线程应用程序中,这只会退出当前线程(并允许稍后在运行它的 Web Worker 中运行代码)。

void emscripten_force_exit(int status)

关闭运行时并退出(终止)程序,就像您调用 exit() 一样。

区别在于 emscripten_force_exit 即使您之前调用了 emscripten_exit_with_live_runtime() 或以其他方式使运行时保持活动状态,也会关闭运行时。换句话说,此方法使您能够在运行时在 main() 完成后继续保持活动状态的情况下,完全关闭运行时。

请注意,如果未设置 EXIT_RUNTIME(默认情况下),则无法关闭运行时,因为我们不包含执行此操作的代码。如果您希望能够退出运行时,请使用 -sEXIT_RUNTIME 进行构建。

参数
  • status (int) – 与 libc 函数 exit() 相同。

double emscripten_get_device_pixel_ratio(void)

返回 window.devicePixelRatio 的值。

返回值类型

double

返回值

像素比率或 1.0(如果不受支持)。

char *emscripten_get_window_title()

返回窗口标题。

返回的字符串在函数的下次调用之前将保持有效

void emscripten_set_window_title(char *title)

设置窗口标题。

void emscripten_get_screen_size(int *width, int *height)

返回屏幕的宽度和高度。

void emscripten_hide_mouse(void)

隐藏画布上的操作系统鼠标光标。

请注意,SDL 的 SDL_ShowCursor 命令显示和隐藏 SDL 光标,而不是操作系统光标。此命令在您的应用程序绘制自己的光标时很有用,可以隐藏操作系统光标。

double emscripten_get_now(void)

返回浏览器提供的当前时间的最高精度表示。

这使用 Date.nowperformance.now。结果不是绝对时间,只有在与对该函数的其他调用进行比较时才有意义。

返回值类型

double

返回值

当前时间,以毫秒 (ms) 为单位。

float emscripten_random(void)

在 0-1 范围内生成一个随机数。这映射到 Math.random()

返回值类型

float

返回值

一个随机数。

异步文件系统 API

类型定义

em_async_wget_onload_func

用于 emscripten_async_wget_data()onload 回调的函数指针类型(参数的具体值在该方法中有说明)。

定义为

typedef void (*em_async_wget_onload_func)(void*, void*, int)
em_async_wget2_onload_func

用于 emscripten_async_wget2()onload 回调的函数指针类型(参数的具体值在该方法中有说明)。

定义为

typedef void (*em_async_wget2_onload_func)(void*, const char*)
em_async_wget2_onstatus_func

用于 emscripten_async_wget2()onerroronprogress 回调的函数指针类型(参数的具体值在该方法中有说明)。

定义为

typedef void (*em_async_wget2_onstatus_func)(void*, int)
em_async_wget2_data_onload_func

用于 emscripten_async_wget2_data()onload 回调的函数指针类型(参数的具体值在该方法中有说明)。

定义为

typedef void (*em_async_wget2_data_onload_func)(unsigned, void*, void *, unsigned)
em_async_wget2_data_onerror_func

用于 emscripten_async_wget2_data()onerror 回调的函数指针类型(参数的具体值在该方法中有说明)。

定义为

typedef void (*em_async_wget2_data_onerror_func)(unsigned, void*, int, const char*)
em_async_wget2_data_onprogress_func

用于 emscripten_async_wget2_data()onprogress 回调的函数指针类型(参数的具体值在该方法中有说明)。

定义为

typedef void (*em_async_wget2_data_onprogress_func)(unsigned, void*, int, int)
em_run_preload_plugins_data_onload_func

用于 emscripten_run_preload_plugins_data()onload 回调的函数指针类型(参数的具体值在该方法中有说明)。

定义为

typedef void (*em_run_preload_plugins_data_onload_func)(void*, const char*)

函数

void emscripten_async_wget(const char* url, const char* file, em_str_callback_func onload, em_str_callback_func onerror)

异步从 URL 加载文件。

除了从网络获取 URL 之外,还会执行预加载插件,以便数据在 IMG_Load 等中可用(我们异步执行工作以使浏览器解码图像或音频等)。有关预加载文件的更多信息,请参阅 预加载文件

当文件准备好时,将调用 onload 回调。如果发生任何错误,将调用 onerror。回调将使用文件作为其参数进行调用。

参数
  • char* url (const) – 要加载的 URL。

  • char* file (const) – 从 URL 创建并加载的文件的名称。如果文件已存在,它将被覆盖。如果文件目标目录在文件系统中不存在,它将被创建。可以传递相对路径名,该路径名将被解释为相对于调用此函数时的当前工作目录。

  • onload (em_str_callback_func) –

    成功加载文件时的回调。回调函数参数值为

    • (const char)* : 从 URL 加载的 file 的名称。

  • onerror (em_str_callback_func) –

    发生故障时的回调。回调函数参数值为

    • (const char)* : 从 URL 加载失败的 file 的名称。

void emscripten_async_wget_data(const char* url, void *arg, em_async_wget_onload_func onload, em_arg_callback_func onerror)

异步从 URL 加载缓冲区。

这是 emscripten_async_wget() 的“数据”版本。

此函数不写入文件,而是直接写入内存中的缓冲区。这避免了使用模拟文件系统的开销;但是请注意,由于没有使用文件,因此它无法运行预加载插件来为 IMG_Load 等设置内容(IMG_Load 等在文件上运行)。

当文件准备好时,将调用 onload 回调。如果发生任何错误,将调用 onerror

参数
  • url (const char*) – 要加载的文件的 URL。

  • arg (void*) – 传递给回调的用户定义数据,不受 API 本身影响。回调可以使用它来标识关联的调用。

  • onload (em_async_wget_onload_func) –

    将 URL 成功加载到缓冲区时的回调。回调函数参数值为

    • (void)* : 等于 arg (用户定义数据)。

    • (void)* : 指向包含数据的缓冲区的指针。注意,与 worker API 一样,数据缓冲区只在回调期间存在;它必须在该时间内使用或复制。

    • (int) : 缓冲区的大小,以字节为单位。

  • onerror (em_arg_callback_func) –

    发生错误时的回调。回调函数参数值是

    • (void)* : 等于 arg (用户定义数据)。

int emscripten_async_wget2(const char* url, const char* file, const char* requesttype, const char* param, void *arg, em_async_wget2_onload_func onload, em_async_wget2_onstatus_func onerror, em_async_wget2_onstatus_func onprogress)

异步从 URL 加载文件。

这是一个实验性的“更完整功能”版本,它比 emscripten_async_wget() 更完善。

目前,在下载数据上执行预加载插件。如果您想能够使用 IMG_Load 等操作下载文件,您可能需要在 onload 回调中调用 emscripten_run_preload_plugins()

当文件准备就绪时,将使用 argfile 中给出的对象指针调用 onload 回调。在下载过程中,将调用 onprogress 回调。

参数
  • url (const char*) – 要加载的文件的 URL。

  • file (const char*) – 从 URL 创建并加载的文件的名称。如果文件已经存在,它将被覆盖。如果文件目标目录不存在于文件系统中,它将被创建。可以传递一个相对路径名,该路径名将在调用此函数时相对于当前工作目录进行解释。

  • requesttype (const char*) – ‘GET’ 或 ‘POST’。

  • param (const char*) – POST 请求的请求参数(参见 requesttype)。参数的指定方式与在等效 GET 请求的 URL 中指定参数的方式相同:例如 key=value&key2=value2

  • arg (void*) – 传递给回调的用户定义数据,不受 API 本身影响。回调可以使用它来标识关联的调用。

  • onload (em_async_wget2_onload_func) –

    成功加载文件时的回调。回调函数参数值是

    • (void)* : 等于 arg (用户定义数据)。

    • (const char)* : 传递给原始调用的 file

  • onerror (em_async_wget2_onstatus_func) –

    发生错误时的回调。回调函数参数值是

    • (void)* : 等于 arg (用户定义数据)。

    • (int) : HTTP 状态码。

  • onprogress (em_async_wget2_onstatus_func) –

    加载文件期间的回调。回调函数参数值是

    • (void)* : 等于 arg (用户定义数据)。

    • (int) : 进度(已完成的百分比)。

返回值

请求句柄(int),可用于 abort 请求。

int emscripten_async_wget2_data(const char* url, const char* requesttype, const char* param, void *arg, int free, em_async_wget2_data_onload_func onload, em_async_wget2_data_onerror_func onerror, em_async_wget2_data_onprogress_func onprogress)

异步从 URL 加载缓冲区。

这是 emscripten_async_wget2() 的“数据”版本。它是一个实验性的“更完整功能”版本,它比 emscripten_async_wget_data() 更完善。

此函数不写入文件,而是直接写入内存中的缓冲区。这避免了使用模拟文件系统的开销;但是请注意,由于没有使用文件,因此它无法运行预加载插件来为 IMG_Load 等设置内容(IMG_Load 等在文件上运行)。

当文件准备就绪时,将使用在 arg 中给出的对象指针、指向内存中缓冲区的指针以及包含缓冲区大小的无符号整数调用 onload 回调。在下载过程中,将使用进度信息调用 onprogress 回调。如果发生错误,将使用 HTTP 状态码和包含状态描述的字符串调用 onerror

参数
  • url (const char*) – 要加载的文件的 URL。

  • requesttype (const char*) – ‘GET’ 或 ‘POST’。

  • param (const char*) – POST 请求的请求参数(参见 requesttype)。参数的指定方式与在等效 GET 请求的 URL 中指定参数的方式相同:例如 key=value&key2=value2

  • arg (void*) – 传递给回调的用户定义数据,不受 API 本身影响。回调可以使用它来标识关联的调用。

  • free (int) – 告诉运行时是否在 onload 完成后释放返回的缓冲区。如果为 false,则释放缓冲区是接收者的责任。

  • onload (em_async_wget2_data_onload_func) –

    成功加载文件时的回调。回调函数参数值是

    • (unsigned) : 请求句柄

    • (void)* : 等于 arg (用户定义数据)。

    • (void)* : 指向内存中缓冲区的指针。

    • (unsigned) : 缓冲区的大小(以字节为单位)。

  • onerror (em_async_wget2_data_onerror_func) –

    发生错误时的回调。回调函数参数值是

    • (unsigned) : 请求句柄

    • (void)* : 等于 arg (用户定义数据)。

    • (int) : HTTP 错误码。

    • (const char)* : 包含状态描述的字符串。

  • onprogress (em_async_wget2_data_onprogress_func) –

    在加载文件期间定期调用以更新进度的回调。回调函数参数值是

    • (unsigned) : 请求句柄

    • (void)* : 等于 arg (用户定义数据)。

    • (int) : 已加载的字节数。

    • (int) : 数据的总大小(以字节为单位),如果大小不可用,则为零。

返回值

请求句柄(int),可用于 abort 请求。

void emscripten_async_wget2_abort(int handle)

中止使用 emscripten_async_wget2()emscripten_async_wget2_data() 触发的异步请求。

参数
  • handle (int) – 要中止的请求的句柄。

void emscripten_run_preload_plugins_data(char* data, int size, const char *suffix, void *arg, em_run_preload_plugins_data_onload_func onload, em_arg_callback_func onerror)

异步运行预加载插件处理数据缓冲区。这是 emscripten_run_preload_plugins() 的“数据”版本,它接收原始数据作为输入,而不是文件名(这可以避免先将数据写入文件)。有关预加载插件的更多信息,请参见 预加载文件

当文件加载完毕时,将调用 onload 回调。如果发生任何错误,将调用 onerror

onload 还接收第二个参数,它是一个“伪”文件名,您可以将其传递给 IMG_Load(它不是实际文件,但它为 IMG_Load 识别此图像以便能够处理它)。请注意,此 API 的用户负责为“伪”文件名分配的内存调用 free()

参数
  • data (char*) – 要处理的数据缓冲区。

  • suffix (const char*) – 文件后缀,例如“png”或“jpg”。

  • arg (void*) – 传递给回调的用户定义数据,不受 API 本身影响。回调可以使用它来标识关联的调用。

  • onload (em_run_preload_plugins_data_onload_func) –

    成功处理数据时的回调。回调函数参数值是

    • (void)* : 等于 arg (用户定义数据)。

    • (const char)* : 一个“伪”文件名,您可以将其传递给 IMG_Load。有关更多信息,请参见上文。

  • onerror (em_arg_callback_func) –

    发生故障时的回调。回调函数参数值为

    • (void)* : 等于 arg (用户定义数据)。

void emscripten_dlopen(const char *filename, int flags, void* user_data, em_dlopen_callback onsuccess, em_arg_callback_func onerror);

启动一个异步 dlopen 操作,从文件名或 URL 加载共享库。立即返回,要求调用者返回事件循环。 onsuccessonerror 回调用于指示请求的成功或失败。在 onerror 回调后,可以使用正常的 dlerror C 函数获取错误详细信息。标志与正常 dlopen C 函数中使用的标志相同。

参数
  • char* filename (const) – 要加载的共享库的文件名(或 URL)。

  • flags (int) – 请参见 dlopen 标志。

  • user_data (void*) – 传递给 onsuccess 和 onerror 回调的用户数据。

  • onsuccess (em_dlopen_callback) – 如果库成功加载,则调用。

  • onerror (em_arg_callback_func) – 如果加载库时出现错误,则调用。

异步 IndexedDB API

IndexedDB 是一个浏览器 API,它允许您持久存储数据,也就是说,您可以在那里保存数据,并在用户重新访问网页时加载它。IDBFS 提供了一种使用 IndexedDB 的方法,通过 Emscripten 文件系统层。此处列出的 emscripten_idb_* 方法提供了一个替代 API,直接访问 IndexedDB,从而避免了文件系统层的开销。

void emscripten_idb_async_load(const char *db_name, const char *file_id, void* arg, em_async_wget_onload_func onload, em_arg_callback_func onerror)

异步从本地 IndexedDB 存储加载数据。这允许使用持久数据,而无需文件系统层的开销。

当数据准备就绪时,将调用 onload 回调。如果发生任何错误,将调用 onerror

参数
  • db_name – 要加载的 IndexedDB 数据库。

  • file_id – 要加载的数据的标识符。

  • arg (void*) – 传递给回调的用户定义数据,不受 API 本身影响。回调可以使用它来标识关联的调用。

  • onload (em_async_wget_onload_func) –

    将 URL 成功加载到缓冲区时的回调。回调函数参数值为

    • (void)* : 等于 arg (用户定义数据)。

    • (void)* : 指向包含数据的缓冲区的指针。注意,与 worker API 一样,数据缓冲区只在回调期间存在;它必须在该时间内使用或复制。

    • (int) : 缓冲区的大小,以字节为单位。

  • onerror (em_arg_callback_func) –

    发生错误时的回调。回调函数参数值是

    • (void)* : 等于 arg (用户定义数据)。

void emscripten_idb_async_store(const char *db_name, const char *file_id, void* ptr, int num, void* arg, em_arg_callback_func onstore, em_arg_callback_func onerror);

异步将数据存储到本地 IndexedDB 存储。这允许使用持久数据,而无需文件系统层的开销。

当数据存储完毕时,将调用 onstore 回调函数。如果出现任何错误,将调用 onerror 回调函数。

参数
  • db_name – 要加载的 IndexedDB 数据库。

  • file_id – 要加载的数据的标识符。

  • ptr – 指向要存储数据的指针。

  • num – 要存储的字节数。

  • arg (void*) – 传递给回调的用户定义数据,不受 API 本身影响。回调可以使用它来标识关联的调用。

  • onstore (em_arg_callback_func) –

    成功将数据缓冲区存储到 URL 时的回调函数。回调函数参数值如下:

    • (void)* : 等于 arg (用户定义数据)。

  • onerror (em_arg_callback_func) –

    发生错误时的回调。回调函数参数值是

    • (void)* : 等于 arg (用户定义数据)。

void emscripten_idb_async_delete(const char *db_name, const char *file_id, void* arg, em_arg_callback_func ondelete, em_arg_callback_func onerror)

异步从本地 IndexedDB 存储中删除数据。

当数据删除完毕时,将调用 ondelete 回调函数。如果出现任何错误,将调用 onerror 回调函数。

参数
  • db_name – IndexedDB 数据库名称。

  • file_id – 数据的标识符。

  • arg (void*) – 传递给回调的用户定义数据,不受 API 本身影响。回调可以使用它来标识关联的调用。

  • ondelete (em_arg_callback_func) –

    成功删除时的回调函数。

    • (void)* : 等于 arg (用户定义数据)。

  • onerror (em_arg_callback_func) –

    发生错误时的回调。回调函数参数值是

    • (void)* : 等于 arg (用户定义数据)。

void emscripten_idb_async_exists(const char *db_name, const char *file_id, void* arg, em_idb_exists_func oncheck, em_arg_callback_func onerror)

异步检查本地 IndexedDB 存储中是否存在具有特定 ID 的数据。

当数据检查完毕时,将调用 oncheck 回调函数。如果出现任何错误,将调用 onerror 回调函数。

参数
  • db_name – IndexedDB 数据库名称。

  • file_id – 数据的标识符。

  • arg (void*) – 传递给回调的用户定义数据,不受 API 本身影响。回调可以使用它来标识关联的调用。

  • oncheck (em_idb_exists_func) –

    成功检查时的回调函数,参数如下:

    • (void)* : 等于 arg (用户定义数据)。

    • int : 文件是否存在。

  • onerror (em_arg_callback_func) –

    发生错误时的回调。回调函数参数值是

    • (void)* : 等于 arg (用户定义数据)。

void emscripten_idb_async_clear(const char *db_name, void* arg, em_arg_callback_func onclear, em_arg_callback_func onerror)

异步清除本地 IndexedDB 存储中的所有数据。

当存储清除完毕时,将调用 onclear 回调函数。如果出现任何错误,将调用 onerror 回调函数。

参数
  • db_name – IndexedDB 数据库名称。

  • arg (void*) – 传递给回调的用户定义数据,不受 API 本身影响。回调可以使用它来标识关联的调用。

  • onclear (em_arg_callback_func) –

    成功清除时的回调函数。回调函数参数为:

    • (void)* : 等于 arg (用户定义数据)。

  • onerror (em_arg_callback_func) –

    失败时的回调函数。回调函数参数为:

    • (void)* : 等于 arg (用户定义数据)。

int emscripten_run_preload_plugins(const char* file, em_str_callback_func onload, em_str_callback_func onerror)

异步对文件运行预加载插件。它适用于已存在的文件数据,并执行任何作为预加载插件提供的异步操作,例如为 IMG_Load 解码图像,或为 Mix_LoadWAV 解码音频。有关预加载插件的更多信息,请参阅 预加载文件

操作完成后,将调用 onload 回调函数。如果出现任何错误,将调用 onerror 回调函数。回调函数以文件作为其参数被调用。

参数
  • file (const char*) – 要处理的文件名。

  • onload (em_str_callback_func) –

    成功处理文件时的回调函数。回调函数参数值为:

    • (const char)* : 处理的 file 文件名。

  • onerror (em_str_callback_func) –

    发生故障时的回调。回调函数参数值为

    • (const char)* : 操作失败的 file 文件名。

返回值

成功时为 0,文件不存在时为 -1。

返回值类型

int

编译

EMSCRIPTEN_KEEPALIVE

告诉编译器和链接器保留一个符号,并导出它,就像你把它添加到 EXPORTED_FUNCTIONS 中一样。

例如

void EMSCRIPTEN_KEEPALIVE my_function() { printf("I am being kept alive\n"); }

请注意,这只有在定义符号的对象文件被链接器包含的情况下才会起作用。如果对象文件是归档文件的一部分,并且没有被其他文件引用,链接器根本不会包含它,并且对象文件中的任何符号都不会被包含或导出。解决此限制的一种方法是在归档文件前后使用 -Wl,--whole-archive / -Wl,--no-whole-archive 标记。

Worker API

类型定义

int worker_handle

一个围绕 Web Worker 的包装器,允许你创建 Worker 并与其通信。

请注意,当前的 API 主要侧重于主线程,该线程向 Worker 发送作业并等待响应,即以非对称的方式,目前还没有 API 可以发送消息,而无需由 Worker 请求从 Worker 发送到主线程。

em_worker_callback_func

来自 emscripten_call_worker() 的回调函数指针类型(参数的具体值在该方法中记录)。

定义为

typedef void (*em_worker_callback_func)(char*, int, void*)

函数

worker_handle emscripten_create_worker(const char * url)

创建一个 Worker。

Worker 必须与主程序分开编译,并且 BUILD_AS_WORKER 标记设置为 1。

该 Worker 不应该使用 -pthread 标记进行编译,因为 POSIX 线程实现和此 Worker API 不兼容。

参数
  • url (const char*) – Worker 脚本的 URL。

返回值

新建 Worker 的句柄。

返回值类型

worker_handle

void emscripten_destroy_worker(worker_handle worker)

销毁一个 Worker。请参阅 emscripten_create_worker()

参数
void emscripten_call_worker(worker_handle worker, const char *funcname, char *data, int size, em_worker_callback_func callback, void *arg)

异步调用一个 Worker。

Worker 函数将使用两个参数被调用:一个数据指针和一个大小。指针和大小定义的数据块仅在回调期间存在:之后无法依赖它。如果你需要将部分信息保存在回调范围之外,那么需要将其复制到安全的位置。

被调用的 Worker 函数可以通过调用 emscripten_worker_respond() 返回数据。调用 Worker 时,如果提供了回调函数,它将使用三个参数被调用:数据指针、大小和调用 emscripten_call_worker() 时提供的参数(以便更容易将回调函数与调用关联起来)。数据指针和大小定义的数据块的行为与 Worker 函数中的数据块相同,它仅在回调期间存在。

参数
  • worker (worker_handle) – 要调用的 Worker 的句柄。

  • funcname (const char*) – Worker 中的函数名称。该函数必须是 C 函数(因此没有 C++ 名字重整),并且必须导出(EXPORTED_FUNCTIONS)。

  • data (char*) – 要复制的内存块的地址。

  • size (int) – 内存块的大小。

  • callback (em_worker_callback_func) –

    带有响应的 Worker 回调函数。它可以为 null。回调函数参数值如下:

    • (char)* : 在 emscripten_call_worker() 中提供的 data 指针。

    • (int) : 数据块的 size

    • (void)* : 等于 arg (用户定义数据)。

  • arg (void*) – 传递给回调函数的参数(用户数据)。

void emscripten_worker_respond(char *data, int size)
void emscripten_worker_respond_provisionally(char *data, int size)

在 Worker 调用中发送响应(即,当使用 emscripten_call_worker() 从主线程调用时)。

这两个函数都会将消息回发到调用 Worker 的线程。 emscripten_worker_respond_provisionally() 变体可以多次调用,这将排队消息以发送到 Worker 的创建者。最后,必须调用 _respond 变体,这将禁止进一步的消息,并释放先前为该 Worker 调用分配的框架资源。

注意

调用临时版本是可选的,但你必须调用非临时版本以避免内存泄漏。

参数
  • data (char*) – 要发布的消息。

  • size (int) – 消息的大小(以字节为单位)。

int emscripten_get_worker_queue_size(worker_handle worker)

检查有多少个来自工作线程的响应正在等待。

这仅统计对 emscripten_call_worker() 的调用,这些调用具有回调(忽略没有回调的调用),并且尚未收到响应。这是一种简单的方法来检查工作线程的状态,查看它有多忙,并进行有关限制的基本决策。

参数
  • worker (worker_handle) – 与相关工作线程关联的句柄。

返回值

来自工作线程的响应等待数量。

返回值类型

int

日志记录实用程序

定义

EM_LOG_CONSOLE

如果指定,则直接将日志记录到浏览器控制台/检查器窗口。如果未指定,则通过应用程序模块进行日志记录。

EM_LOG_WARN

如果指定,则打印警告消息(与 EM_LOG_CONSOLE 相结合)。

EM_LOG_INFO

如果指定,则将信息消息打印到控制台(与 EM_LOG_CONSOLE 相结合)。

EM_LOG_DEBUG

如果指定,则将调试消息打印到控制台(与 EM_LOG_CONSOLE 相结合)。

EM_LOG_ERROR

如果指定,则打印错误消息(与 EM_LOG_CONSOLE 相结合)。如果未指定 EM_LOG_WARNEM_LOG_ERROREM_LOG_INFOEM_LOG_DEBUG,则会打印一条日志消息。 EM_LOG_WARNEM_LOG_INFOEM_LOG_DEBUGEM_LOG_ERROR 是互斥的。如果未指定 EM_LOG_CONSOLE,则消息将通过 err() 输出(对于 EM_LOG_ERROREM_LOG_WARN)或通过 out() 输出(对于其他情况)。

EM_LOG_C_STACK

如果指定,则打印一个调用堆栈,其中包含使用源映射信息引用原始 C 源代码的文件名。

EM_LOG_JS_STACK

如果指定,则打印一个包含引用已构建的 .js/.html 文件中的行的文件名以及消息的调用堆栈。标志 EM_LOG_C_STACKEM_LOG_JS_STACK 可以结合使用,以输出未翻译和翻译后的文件和行信息。

EM_LOG_NO_PATHS

如果指定,则调用堆栈中的文件信息的路径名将被省略。

函数

long emscripten_get_compiler_setting(const char *name)

返回编译器设置的值。

例如,要返回编译期间 INITIAL_MEMORY 值的整数值

emscripten_get_compiler_setting("INITIAL_MEMORY")

对于包含除整数以外的其他内容的值,将返回字符串(需要将 long 返回值强制转换为 char*)。

这可以做一些有用的事情,例如提供 Emscripten 的版本(“EMSCRIPTEN_VERSION”)、优化级别(“OPT_LEVEL”)、调试级别(“DEBUG_LEVEL”)等。

为了使此命令起作用,必须使用以下编译器选项进行构建(因为我们不想因为此元数据而增加构建大小)

-sRETAIN_COMPILER_SETTINGS
参数
  • name (const char*) – 要返回的编译器设置。

返回值

指定设置的值。请注意,对于除整数以外的值,将返回字符串(将 int 返回值强制转换为 char*)。

返回值类型

int

int emscripten_has_asyncify()

返回是否可以使用伪同步函数。

返回值类型

int

返回值

如果程序使用 -sASYNCIFY 编译,则为 1,否则为 0。

void emscripten_debugger()

发出 debugger

这在代码中是内联的,如果到达这里,它将告诉 JavaScript 引擎调用调试器。

void emscripten_log(int flags, const char* format, ...)

将消息打印到控制台,可以选择包含调用堆栈信息。

参数
  • flags (int) – EM_LOG_xxx 标志列表中项目的二进制 OR,指定打印选项。

  • char* format (const) – printf 样式的格式字符串。

  • ...printf 样式的 “…” 参数列表,根据 printf 格式化规则进行解析。

int emscripten_get_callstack(int flags, char *out, int maxbytes)

以编程方式获取当前调用堆栈。

要查询调用堆栈所需的字节量,而无需写入它,请将 0 传递给 outmaxbytes,在这种情况下,该函数将返回保存完整调用堆栈所需的字节数(包括终止零)。请注意,这可能不是完全准确的,因为后续调用将携带不同的行号,因此最好多分配几个字节以确保安全。

参数
  • flags (int) – EM_LOG_xxx 标志列表中项目的二进制 OR,指定打印选项。标志 EM_LOG_CONSOLEEM_LOG_WARNEM_LOG_ERROR 不适用于此函数,将被忽略。

  • out (char*) – 指向内存区域的指针,调用堆栈字符串将被写入到该区域。此函数输出的字符串将始终以 null 结尾。

  • maxbytes (int) – 此函数可以写入由 out 指向的内存的字节数的最大值。如果没有足够的可用空间,则输出将被截断(但始终以 null 结尾)。

返回值

写入的字节数(不是字符数,因此这也将包括终止零)。

返回值类型

int

char *emscripten_get_preloaded_image_data(const char *path, int *w, int *h)

获取预加载的图像数据和图像大小。

该函数返回指向加载的图像的指针或 NULL — 该指针应被 free()。如果数据有效,则图像的宽度/高度将被写入到 wh 参数。

参数
  • path (const char*) – 包含预加载图像的文件的完整路径/文件名。

  • w (int*) – 图像的宽度(如果数据有效)。

  • h (int*) – 图像的高度(如果数据有效)。

返回值

指向预加载图像的指针或 NULL。

返回值类型

char*

char *emscripten_get_preloaded_image_data_from_FILE(FILE *file, int *w, int *h)

从 C FILE* 获取预加载的图像数据。

参数
  • file (FILE*) – 包含预加载图像的 FILE

  • w (int*) – 图像的宽度(如果数据有效)。

  • h (int*) – 图像的高度(如果数据有效)。

返回值

指向预加载图像的指针或 NULL。

返回值类型

char*

int emscripten_print_double(double x, char *to, signed max)

将双精度浮点数以字符串形式打印,包括空终止符。这很有用,因为 JS 引擎很好地支持以最小可能大小打印双精度浮点数的方式,同时保留双精度浮点数中的所有信息,即它可以以完全可逆的方式解析回来(不幸的是,snprintf 等不能这样做)。

参数
  • x (double) – 双精度浮点数。

  • to (char*) – 预先分配的足够大小的缓冲区,如果不需要输出,则为 NULL(用于获取必要的大小)。

  • max (signed) – 可以写入输出指针“to”的最大字节数(包括空终止符)。

返回值类型

必要的字节数,不包括空终止符(如果 to 不为 NULL,则实际写入)。

套接字事件注册

本节中的函数注册用于接收套接字事件的回调函数。这些事件类似于 WebSocket 事件,但在内部 Emscripten 套接字处理发生后发出。这意味着,例如,消息回调将在数据添加到recv_queue之后触发,因此接收此回调的应用程序可以简单地使用作为回调参数传递的文件描述符读取数据。所有回调都传递一个文件描述符 (fd),表示发生通知活动的套接字。错误回调还获取一个表示套接字错误号的 int (errno) 和一个表示错误消息的 char* (msg)。

每个给定事件只能注册一个回调函数,因此多次调用给定注册函数将导致第一个回调被替换。类似地,将 NULL 回调函数传递给任何 emscripten_set_socket_*_callback 调用将取消注册为该事件注册的回调。

userData 指针允许在事件注册期间指定的任意数据传递给回调,这对于在面向对象代码中传递 this 指针特别有用。

除了能够从 C 注册网络回调之外,本机 JavaScript 代码还可以直接使用用于实现回调注册的底层机制。例如,以下代码显示了当 SOCKET_DEBUG 启用时默认注册的简单日志记录回调。

Module['websocket']['on']('error', function(error) {console.log('Socket error ' + error);});
Module['websocket']['on']('open', function(fd) {console.log('Socket open fd = ' + fd);});
Module['websocket']['on']('listen', function(fd) {console.log('Socket listen fd = ' + fd);});
Module['websocket']['on']('connection', function(fd) {console.log('Socket connection fd = ' + fd);});
Module['websocket']['on']('message', function(fd) {console.log('Socket message fd = ' + fd);});
Module['websocket']['on']('close', function(fd) {console.log('Socket close fd = ' + fd);});

上面大多数 JavaScript 回调函数都传递了触发回调的套接字的文件描述符,但错误回调传递的是一个数组,其中包含文件描述符、错误代码和错误消息。

注意

底层 JavaScript 实现不会传递 userData。这主要对 C/C++ 代码有用,而 emscripten_set_socket_*_callback 调用只是创建一个包含 userData 的闭包,并将该闭包作为回调传递给底层 JavaScript 事件注册机制。

回调函数

em_socket_callback

用于 emscripten_set_socket_open_callback() 和其他套接字函数(除了 emscripten_set_socket_error_callback())的函数指针。定义如下:

typedef void (*em_socket_callback)(int fd, void *userData);
参数
  • fd (int) – 触发回调的套接字的文件描述符。

  • userData (void*) – 最初传递给事件注册函数的 userData

em_socket_error_callback

用于 emscripten_set_socket_error_callback() 的函数指针,定义如下:

typedef void (*em_socket_error_callback)(int fd, int err, const char* msg, void *userData);
参数
  • fd (int) – 触发回调的套接字的文件描述符。

  • err (int) – 发生的错误代码。

  • msg (int) – 发生的错误消息。

  • userData (void*) – 最初传递给事件注册函数的 userData

函数

void emscripten_set_socket_error_callback(void *userData, em_socket_error_callback callback)

WebSocket 错误触发。

有关更多信息,请参阅 套接字事件注册

参数
  • userData (void*) – 传递给回调的任意用户数据。

  • callback (em_socket_error_callback) – 指向回调函数的指针。回调返回文件描述符、错误代码和消息,以及传递给此函数的任意 userData

void emscripten_set_socket_open_callback(void *userData, em_socket_callback callback)

WebSocket 已打开时触发。

有关更多信息,请参阅 套接字事件注册

参数
  • userData (void*) – 传递给回调的任意用户数据。

  • callback (em_socket_callback) – 指向回调函数的指针。回调返回文件描述符和传递给此函数的任意 userData

void emscripten_set_socket_listen_callback(void *userData, em_socket_callback callback)

当调用 listen 时触发(合成事件)。

有关更多信息,请参阅 套接字事件注册

参数
  • userData (void*) – 传递给回调的任意用户数据。

  • callback (em_socket_callback) – 指向回调函数的指针。回调返回文件描述符和传递给此函数的任意 userData

void emscripten_set_socket_connection_callback(void *userData, em_socket_callback callback)

当连接已建立时触发。

有关更多信息,请参阅 套接字事件注册

参数
  • userData (void*) – 传递给回调的任意用户数据。

  • callback (em_socket_callback) – 指向回调函数的指针。回调返回文件描述符和传递给此函数的任意 userData

void emscripten_set_socket_message_callback(void *userData, em_socket_callback callback)

当套接字上有可读数据时触发。

有关更多信息,请参阅 套接字事件注册

参数
  • userData (void*) – 传递给回调的任意用户数据。

  • callback (em_socket_callback) – 指向回调函数的指针。回调返回文件描述符和传递给此函数的任意 userData

void emscripten_set_socket_close_callback(void *userData, em_socket_callback callback)

WebSocket 已关闭时触发。

有关更多信息,请参阅 套接字事件注册

参数
  • userData (void*) – 传递给回调的任意用户数据。

  • callback (em_socket_callback) – 指向回调函数的指针。回调返回文件描述符和传递给此函数的任意 userData

未对齐类型

类型定义

emscripten_align1_short
emscripten_align2_int
emscripten_align1_int
emscripten_align2_float
emscripten_align1_float
emscripten_align4_double
emscripten_align2_double
emscripten_align1_double

未对齐类型。这些类型可用于强制 LLVM 在代码中 SAFE_HEAP 发现未对齐操作的位置发出未对齐的加载/存储。

有关使用示例,请参阅 test/core/test_set_align.c

注意

最好避免未对齐的操作,但如果您要从字节流或类似内容中读取数据,这些类型可能会很有用!

伪同步函数

这些函数需要 Asyncify (-sASYNCIFY)。这些函数是异步的,但在 C 中表现为同步。有关更多详细信息,请参阅 Asyncify

休眠

void emscripten_sleep(unsigned int ms)

休眠 ms 毫秒。这对代码来说似乎是一个普通的“同步”休眠,也就是说,执行不会在休眠完成之前继续到下一行源代码。但是请注意,这是使用返回事件循环实现的(在 Web 上不可能以阻塞方式实际休眠),这意味着其他异步事件可能会发生。

网络

int emscripten_wget(const char* url, const char* file)

同步从 url 加载文件。有关异步版本,请参阅 emscripten_async_wget()

除了从网络获取 URL 外,还会执行预加载插件,以便数据在 IMG_Load 等中可用(我们会同步执行工作,让浏览器解码图像或音频等)。有关预加载文件的更多信息,请参见 预加载文件

此函数是阻塞的;它将不会返回,直到所有操作完成。如果成功,您就可以打开并读取文件。

参数
  • char* url (const) – 要加载的 URL。

  • char* file (const) – 从 URL 创建并加载的文件的名称。如果文件已存在,它将被覆盖。如果文件目标目录在文件系统中不存在,它将被创建。可以传递相对路径名,该路径名将被解释为相对于调用此函数时的当前工作目录。

返回值

成功返回 0,错误返回 1。

void emscripten_wget_data(const char* url, void** pbuffer, int* pnum, int *perror);

同步从网络获取数据,并将其存储到内存中的缓冲区,该缓冲区将为您分配。您必须释放缓冲区,否则会造成内存泄漏!

参数
  • url – 要获取的 URL

  • pbuffer – 一个输出参数,它将填充一个指向包含下载数据的缓冲区的指针。此空间已为您分配,您必须释放它,否则会造成内存泄漏!

  • pnum – 一个输出参数,它将填充下载数据的的大小。

  • perror – 一个输出参数,如果发生错误,它将填充一个非零值。

IndexedDB

void emscripten_idb_load(const char *db_name, const char *file_id, void** pbuffer, int* pnum, int *perror);

同步从 IndexedDB 获取数据,并将其存储到内存中的缓冲区,该缓冲区将为您分配。您必须释放缓冲区,否则会造成内存泄漏!

参数
  • db_name – 要加载的数据库的名称

  • file_id – 要加载的文件的名称

  • pbuffer – 一个输出参数,它将填充一个指向包含下载数据的缓冲区的指针。此空间已为您分配,您必须释放它,否则会造成内存泄漏!

  • pnum – 一个输出参数,它将填充下载数据的的大小。

  • perror – 一个输出参数,如果发生错误,它将填充一个非零值。

void emscripten_idb_store(const char *db_name, const char *file_id, void* buffer, int num, int *perror);

同步将数据存储到 IndexedDB。

参数
  • db_name – 要存储的数据库的名称

  • file_id – 要存储的文件的名称

  • buffer – 指向要存储数据的指针

  • num – 要存储的字节数

  • perror – 一个输出参数,如果发生错误,它将填充一个非零值。

void emscripten_idb_delete(const char *db_name, const char *file_id, int *perror);

同步从 IndexedDB 删除数据。

参数
  • db_name – 要删除的数据库的名称

  • file_id – 要删除的文件的名称

  • perror – 一个输出参数,如果发生错误,它将填充一个非零值。

void emscripten_idb_exists(const char *db_name, const char *file_id, int* pexists, int *perror);

同步检查 IndexedDB 中是否存在文件。

参数
  • db_name – 要检查的数据库的名称

  • file_id – 要检查的文件的名称

  • pexists – 一个输出参数,如果文件存在于该数据库中,它将填充一个非零值。

  • perror – 一个输出参数,如果发生错误,它将填充一个非零值。

void emscripten_idb_clear(const char *db_name, int *perror);

同步清除 IndexedDB 中的所有数据。

参数
  • db_name – 要清除的数据库的名称

  • perror – 一个输出参数,如果发生错误,它将填充一个非零值。

异步函数

这些函数仅在使用 Asyncify 时才有效。

类型定义

em_scan_func

用于扫描回调的函数指针类型,接收两个指针,用于内存范围的开始和结束。然后,您可以扫描该范围。

定义为

typedef void (*em_scan_func)(void*, void*)

函数

void emscripten_scan_stack(em_scan_func func)

扫描 C 用户空间堆栈,这意味着由编译代码管理的堆栈(与 Wasm VM 的内部堆栈相反,后者是不可直接观察的)。此数据已存在于线性内存中;此函数只是为您提供了一种简单的方法来了解它在哪里。

void emscripten_scan_registers(em_scan_func func)

扫描“寄存器”,这意味着存储在内存中的数据。在 Wasm 中,这意味着存储在局部变量中的数据,包括堆栈中更高函数的局部变量 - Wasm VM 已经将它们溢出,但用户代码无法观察到它们。

请注意,此函数扫描 Wasm 局部变量。根据 LLVM 优化级别,这可能不会扫描源代码中的原始局部变量。例如,在 -O0 中,局部变量可能存储在堆栈上。为了确保您扫描所有必要的内容,您还可以执行 emscripten_scan_stack

此函数需要 Asyncify - 它依赖于该选项将局部状态一直溢出到堆栈顶部。因此,它将增加程序的开销。

void emscripten_lazy_load_code()

这在编译时创建两个 Wasm 文件:第一个 Wasm 被正常下载并运行,第二个被延迟加载。当遇到 emscripten_lazy_load_code() 调用时,我们将加载第二个 Wasm 并使用它恢复执行。

这里的想法是,如果在代码库中放置了足够多的 emscripten_lazy_load_code() 调用,那么初始下载可能会很小,因为优化器可以从第一个 Wasm 中删除代码,因为它可以看到该代码无法访问。第二个下载的 Wasm 可以包含您的完整代码库,包括很少使用的函数,在这种情况下,延迟加载可能根本不会发生。

注意

这需要使用 -sASYNCIFY_LAZY_LOAD_CODE 构建。

ABI 函数

以下函数未在 emscripten.h 中声明,但在我们系统库的内部使用。如果您替换了 Emscripten 运行时 JS 代码,或在您自己的运行时运行 Emscripten 二进制文件,您可能需要了解它们。

void emscripten_notify_memory_growth(i32 index)

当内存增长时调用。在 JS 运行时,这用于了解何时更新 JS 对 Wasm 内存的视图,否则我们将需要在任何 Wasm 代码运行后不断检查它们。请参见 此 wasi 讨论

参数
  • index (i32) – 哪个内存已增长。