我有一个简单的c函数。
void fill(float *a, float *b)
{
a[0] = 1;
b[0] = 2;
}
int main()
{
float a[1];
float b[1];
fill(a, b);
printf("%f\n", a[0]);
printf("%f\n", b[0]);
return 0;
}这让我
1.000000
2.000000现在,我正在尝试做同样的事情,但通过JavaScript通过WebAssembly。
var wasmModule = new WebAssembly.Module(wasmCode);
var wasmInstance = new WebAssembly.Instance(wasmModule, wasmImports);
const a = new Float32Array(wasmInstance.exports.memory.buffer, 0, 1)
const b = new Float32Array(wasmInstance.exports.memory.buffer, 4, 1)
wasmInstance.exports.fill(a, b)
log(a)
log(b)这是黄蜂小提琴https://wasdk.github.io/WasmFiddle/?19x523
这次a是[2],b是[0]。我想我的记忆出了点问题。我假设a和b都指向内存的开头。这就是为什么a是第一个[1],然后是[2]。我认为,new Float32Array(wasmInstance.exports.memory.buffer, 4, 1)中偏移量为4的偏移量以某种方式被转换为WebAssembly。
如何实现a和b实际上使用不同的内存?谢谢。我真的被困住了。
发布于 2019-07-18 02:27:43
导出的函数调用有问题:
wasmInstance.exports.fill(a,b)
a和b是JS Float32Array对象。从不假定任何JS对象都会自动转换为任何C数据类型。虽然JS TypedArray的行为类似于C数组,但TypedArray仍然是一个基本上是键值存储的JS对象,那么C如何访问JS对象的字段呢?C不知道如何处理JS对象。
WebAssembly类型
好的,让我们在WebAssembly的较低级别上更仔细地研究它。以下是void fill(float *a, float *b)的编译结果
(func $fill (; 0 ;) (param $0 i32) (param $1 i32)
(i32.store
(get_local $0)
(i32.const 1065353216)
)
(i32.store
(get_local $1)
(i32.const 1073741824)
)
)我不会详细讨论细节,但至少很容易理解这个函数$fill需要两个i32类型的参数:(param $0 i32) (param $1 i32)。因此,fill() 需要数字,而不是TypedArrays作为参数。WebAssembly将下列类型定义为函数参数类型和返回类型:i32、i64、f32、f64,基本上是32/64位中间层/浮点数。没有其他类型像JS键值存储,甚至没有数组类型。
因此,无论您在wasmInstance.exports端使用哪种语言,都不应该将任何JS类型直接传递给下的函数。(如Golang、Rust和Emscripten C++ (非C) )通过在JS端封装导出的函数,以及对这些数字类型和Wasm内存地址进行黑客攻击(因此需要一个定义良好的ABI),为无缝类型转换提供了接口。但是,如果直接通过WebAssembly.Instance.exports访问导出的函数,则仍然只能传递数字类型。
存取阵列
那么,您需要传递给fill()的整数值是多少?我认为你已经接近了问题的答案,因为你正确地设置了数组的偏移量。您需要将C指针的值作为整数传递。在Wasm线性存储器中,C指针是对Wasm存储器的偏移地址。因此,您需要像这样稍微修改代码:
var wasmModule = new WebAssembly.Module(wasmCode);
var wasmInstance = new WebAssembly.Instance(wasmModule, wasmImports);
const ptrA = 0; // Yeah it's the same value as NULL, I'd avoid using zero...
const ptrB = 4;
const a = new Float32Array(wasmInstance.exports.memory.buffer, ptrA, 1)
const b = new Float32Array(wasmInstance.exports.memory.buffer, ptrB, 1)
wasmInstance.exports.fill(ptrA, ptrB)
log(a)
log(b)现在你将得到你想要的价值;)
https://stackoverflow.com/questions/57056652
复制相似问题