首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >WebAssembly <-> JavaScript内存交互与多类型数组是如何工作的?

问WebAssembly <-> JavaScript内存交互与多类型数组是如何工作的?
EN

Stack Overflow用户
提问于 2019-07-16 11:54:10
回答 1查看 1.2K关注 0票数 6

我有一个简单的c函数。

代码语言:javascript
复制
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;
}

这让我

代码语言:javascript
复制
1.000000
2.000000

现在,我正在尝试做同样的事情,但通过JavaScript通过WebAssembly。

代码语言:javascript
复制
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实际上使用不同的内存?谢谢。我真的被困住了。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 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)的编译结果

代码语言:javascript
复制
 (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存储器的偏移地址。因此,您需要像这样稍微修改代码:

代码语言:javascript
复制
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)

现在你将得到你想要的价值;)

相关:T数组到JS Blob或UInt8Array

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57056652

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档