html页面传数组参数,将JavaScript数组作为参数传递给WebAssembly函数

我想测试WebAssembly做一些复杂的数组计算.

所以我写了一个简单的C函数,添加了两个int数组,每个数组包含3个元素:

// hello.cpp

extern "C" {

void array_add(int * summed, int* a, int* b) {

for (int i=0; i < 3; i++) {

summed[i] = a[i] + b[i];

}

}

}

并编译了这个:

emcc hello.cpp -s WASM = 1 -s“MODULARIZE = 1”-s“EXPORT_NAME =’HELLO’” – “BINARYEN_METHOD =’native-wasm’” – “EXPORTED_FUNCTIONS = [‘_ array_add’]”-o build /hello.js

其中包括js和wasm文件.我用以下html页面加载这些:

function reqListener () {

// Loading wasm module

var arrayBuffer = oReq.response

HELLO['wasmBinary'] = arrayBuffer

hello = HELLO({ wasmBinary: HELLO.wasmBinary })

// Calling function

var result = new Int32Array(3)

var a = new Int32Array([1, 2, 3])

var b = new Int32Array([4, 5, 2])

hello._array_add(result, a, b)

console.log('result', result)

}

var oReq = new XMLHttpRequest();

oReq.responseType = "arraybuffer";

oReq.addEventListener("load", reqListener);

oReq.open("GET", "build/hello.wasm");

oReq.send();

但不知何故,结果数组总是[0,0,0].

我尝试过各种各样的事情,包括使用ccall()调用函数(参见emscripten docs),似乎我无法将一个数组作为mym编译函数的参数传递.

例如,使用以下C函数:

extern "C" {

int first(int * arr) {

return arr[0];

}

}

在JavaScript中调用的结果是random-ish整数,而不是我作为参数传递的数组的期望值.

我错过了什么?

注意:我对C几乎一无所知,所以如果这是一个与我的C无知相关的初学者问题,那么所有道歉……

解决方法:

您的问题与this one非常相似:WebAssembly仅支持i32 / i64 / f32 / f64 value types以及i8 / i16存储.

这意味着您无法传入指针.当你从C观点来看时,你所做的事情是完全理智的(不需要为无知而道歉!),但这并不是WebAssembly的边界是如何运作的.这也让C专家感到惊讶.

在字符串问题中,您需要:

>通过每个条目调用一次导出(例如set(size_t index,int value)),一次复制一个数组.

>将WebAssembly实例的堆作为ArrayBuffer暴露给JavaScript,并将所需的值直接写入ArrayBuffer.

您可以使用我在另一个答案中提出的相同代码来执行后者:

const bin = ...; // WebAssembly binary, I assume below that it imports a memory from module "imports", field "memory".

const module = new WebAssembly.Module(bin);

const memory = new WebAssembly.Memory({ initial: 2 }); // Size is in pages.

const instance = new WebAssembly.Instance(module, { imports: { memory: memory } });

const arrayBuffer = memory.buffer;

const buffer = new Uint8Array(arrayBuffer);

来自C你可能想知道:“但指针是如何工作的?”上面我解释一下WebAssembly↔JavaScript你无法传递指针!内部WebAssembly指针表示为简单的i32值. Empscripten依赖于LLVM来实现这一点,并且由于WebAssembly将自身呈现为具有4GiB最大堆大小的ILP32,因此Just Works.

它确实对间接函数调用和函数指针有意义!我会留下另一个问题;-)

然而,这确实意味着JavaScript可以“谈论”指向WebAssembly的指针:i32是i32.如果你知道某个值在堆中的某个位置,那么你可以将i32传递给JavaScript,JavaScript可以修改它并将其传回WebAssembly.如果JavaScript可以访问堆的ArrayBuffer,那么拥有i32可以让你知道堆中的位置,并像修改C那样修改堆.

WebAssembly堆与大多数C堆不同:它无法访问可执行页面,也无法访问调用堆栈(或者更确切地说,大多数调用堆栈:LLVM等编译器可能会“溢出”某些地址-taken值到堆而不是使用WebAssembly的本地).这基本上就是哈佛架构所做的(而不是冯·诺伊曼).

那你的hello._array_add(结果,a,b)做什么呢?使用ToInteger从数组中强制a和b.它变为0,在WebAssembly中是一个有效的堆位置!您正在访问堆中非常意外的部分!

标签:emscripten,webassembly,javascript,c,browser

来源: https://codeday.me/bug/20191003/1851076.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值