在 emscripten 中处理输出缓冲区
Handling output buffers in emscripten
假设我有一个 C API 如下:
void get_result_buffer(context* ctx, void** result, size_t* result_size);
其中 context
是一些任意的不透明上下文类型保持状态。预期的调用方式是
context* ctx = ...;
do_something_with_context(ctx, ...);
void* result_buffer = 0;
size_t result_buffer_size = 0;
get_result_buffer(ctx, &result_buffer, &result_buffer_size);
/* Now result_buffer and result_buffer_size are meaningful and populated with the results of having called `do_something_with_context`. */
result_buffer
属于 context
对象,因此调用者不需要释放它。现在我希望能够从 Emscripten 调用 get_result_buffer
。我可以很容易地为此设置 cwrap
,它看起来像:
wrap_get_result_buffer = something.cwrap(
'get_result_buffer',
null,
['number', 'number', 'number']
)
但我不清楚如何设置才能使 JS 中的输出参数 "work"。理想情况下,最后我会得到一些看起来像字节缓冲区的东西,其中包含 result
out 参数指向的数据副本,其长度由 result_size
out 参数描述。
似乎我传入的值需要以某种方式进行分配,然后我会将生成的分配句柄作为 number
类型参数传入,但我不知道如何在JS/Emscripten 层。同样,在调用之后,我希望这些值现在已被转换后的 C 代码更新,但我不清楚如何将现在填充的数据提取到某种 JS 字节数组中。
关于如何执行此操作的任何指导或指向示例代码的指针?
好的。我想通了。对于未来的 emscripteners,您想做如下的事情。
var out_data_ptr = Module._malloc(8)
var out_data_array = new Uint32Array(Module.HEAPU32.buffer, out_data_ptr, 2)
wrap_get_result_buffer(context, out_data_ptr, out_data_ptr + 4)
var response_uint8_array = new Uint8Array(Module.HEAPU8.buffer, out_data_array[0], out_data_array[1])
Module._free(out_data_ptr)
这里的操作理论是,我们创建一个双元素数组,它将存储要通过调用 get_result_buffer
填充的 'slots',然后构造一个视图,将其公开为两个number
兼容元素。然后我们将它们传递给我们的 get_result_buffer
函数,就像上面使用 cwrap
提升的那样。之后,context
所指的堆内存可以从这些槽中访问,然后可以使用这些槽来构造一个 Uint8Array
,它提供对结果中字节的 JS 级访问。
假设我有一个 C API 如下:
void get_result_buffer(context* ctx, void** result, size_t* result_size);
其中 context
是一些任意的不透明上下文类型保持状态。预期的调用方式是
context* ctx = ...;
do_something_with_context(ctx, ...);
void* result_buffer = 0;
size_t result_buffer_size = 0;
get_result_buffer(ctx, &result_buffer, &result_buffer_size);
/* Now result_buffer and result_buffer_size are meaningful and populated with the results of having called `do_something_with_context`. */
result_buffer
属于 context
对象,因此调用者不需要释放它。现在我希望能够从 Emscripten 调用 get_result_buffer
。我可以很容易地为此设置 cwrap
,它看起来像:
wrap_get_result_buffer = something.cwrap(
'get_result_buffer',
null,
['number', 'number', 'number']
)
但我不清楚如何设置才能使 JS 中的输出参数 "work"。理想情况下,最后我会得到一些看起来像字节缓冲区的东西,其中包含 result
out 参数指向的数据副本,其长度由 result_size
out 参数描述。
似乎我传入的值需要以某种方式进行分配,然后我会将生成的分配句柄作为 number
类型参数传入,但我不知道如何在JS/Emscripten 层。同样,在调用之后,我希望这些值现在已被转换后的 C 代码更新,但我不清楚如何将现在填充的数据提取到某种 JS 字节数组中。
关于如何执行此操作的任何指导或指向示例代码的指针?
好的。我想通了。对于未来的 emscripteners,您想做如下的事情。
var out_data_ptr = Module._malloc(8)
var out_data_array = new Uint32Array(Module.HEAPU32.buffer, out_data_ptr, 2)
wrap_get_result_buffer(context, out_data_ptr, out_data_ptr + 4)
var response_uint8_array = new Uint8Array(Module.HEAPU8.buffer, out_data_array[0], out_data_array[1])
Module._free(out_data_ptr)
这里的操作理论是,我们创建一个双元素数组,它将存储要通过调用 get_result_buffer
填充的 'slots',然后构造一个视图,将其公开为两个number
兼容元素。然后我们将它们传递给我们的 get_result_buffer
函数,就像上面使用 cwrap
提升的那样。之后,context
所指的堆内存可以从这些槽中访问,然后可以使用这些槽来构造一个 Uint8Array
,它提供对结果中字节的 JS 级访问。