WebAssembly:从 JavaScript 中的参数(带有内存地址)获取字符串的正确方法
Posted
技术标签:
【中文标题】WebAssembly:从 JavaScript 中的参数(带有内存地址)获取字符串的正确方法【英文标题】:WebAssembly: Correct way to get a string from a parameter (with memory address) in JavaScript 【发布时间】:2018-07-27 16:47:40 【问题描述】:我试图了解 C 代码到 WebAssembly 的转换和 javascript 互操作是如何在后台工作的。而且我在从函数参数中获取简单字符串时遇到问题。
我的程序是一个简单的 Hello World,我正在尝试“模拟”printf
/puts
。
或多或少是我想要构建的 C 等价物:
int main()
puts("Hello World\n");
您可以看到一个工作示例here。
我目前最好的想法是一次读取 16 位内存块(因为 wasm 似乎以 16 位间隔分配它们)并检查空终止。
function get_string(memory, addr)
var length = 0;
while (true)
let buffer = new Uint8Array(memory.buffer, addr, 16);
let term = buffer.indexOf(0);
length += term == -1 ? 16 : term;
if (term != -1) break;
const strBuf = new Uint8Array(memory.buffer, addr, length);
return new TextDecoder().decode(strBuf);
但这看起来真的很笨拙。如果只知道起始地址,有没有更好的方法从内存中读取字符串?
我真的有必要一次只读取 16 位块吗? 如果创建内存的类型化数组算作访问整个内存,或者仅当我尝试从数组中获取数据时才会发生这种情况,我找不到任何信息。
【问题讨论】:
Emscipten 中的胶水代码 ccall 对您有帮助吗? kripken.github.io/emscripten-site/docs/api_reference/…github.com/kripken/emscripten/blob/… 【参考方案1】:WebAssembly 在 64k 页中分配内存。也许这就是 16 位的来源,因为 16 位可以寻址 64 KB。然而,这与手头的任务无关,因为 WebAssembly 内存只是一个连续的地址空间,memory
对象和给定大小的ArrayBuffer
之间没有太大区别,如果有的话。
一次 16 字节的窗口也不是必需的(不知何故,16 位变成了 16 字节)。
您可以简单地执行此操作而不会降低性能,并通过以下方式创建缓冲区其余部分的视图:
function get_string(memory, addr)
let buffer = new Uint8Array(memory.buffer, addr, memory.buffer.byteLength - addr);
let term = buffer.indexOf(0);
return new TextDecoder().decode(buffer.subarray(0, term));
【讨论】:
以上是关于WebAssembly:从 JavaScript 中的参数(带有内存地址)获取字符串的正确方法的主要内容,如果未能解决你的问题,请参考以下文章
如何从 WebAssembly 函数返回 JavaScript 字符串
WebAssembly:从 JavaScript 中的参数(带有内存地址)获取字符串的正确方法
如何从 JavaScript 执行 Kotlin WebAssembly 函数?