gpt4 book ai didi

javascript - 如何解析 Rust 和 WebAssembly 中的函数指针

转载 作者:行者123 更新时间:2023-11-29 07:59:36 25 4
gpt4 key购买 nike

我想提供一个带有接受 Rust 函数指针的外部 JavaScript 函数的 WebAssembly 模块。

一旦这个 JS 模块被初始化,它将调用 .wasm 模块中的 run() 函数,然后调用 peekaboo:

window.Module = {};

const imports = {
env: {
memoryBase: 0,
tableBase: 0,
memory: new WebAssembly.Memory({ initial: 256 }),
table: new WebAssembly.Table({ initial: 4, element: 'anyfunc' })
}
};

imports.env.peekaboo = function(f) {
const fn = imports.env.table.get(f);
return fn(2);
};

fetch('game.wasm')
.then(response => response.arrayBuffer())
.then(bytes => WebAssembly.compile(bytes))
.then(mod => WebAssembly.instantiate(mod, imports))
.then(mod => {
mod.exports.run();

Module.memory = imports.env.memory;
Module.dealloc_str = mod.exports.dealloc_str;
});

我看到的例子表明,如果我以这种方式导入内存,我应该能够使用来解析我的函数指针。这是 Rust 代码:

#![feature(wasm_import_memory)]
#![wasm_import_memory]

extern "C" {
fn peekaboo(f: fn(u32) -> u32);
}

fn main() {}

#[no_mangle]
pub fn run() {
let plus_one = |x: u32| -> u32 { x + 1 };

unsafe {
peekaboo(plus_one);
}
}

一切都编译正常,但是当我执行peekaboo函数时,fn变量为null,表明该表无法找到函数指针。因此执行 fn(2) 会爆炸:

Uncaught (in promise) TypeError: fn is not a function

我或多或少关注了this example但由于我在 Rust 工作,翻译不是一对一的。我怀疑我忽略了一些对我来说不明显的东西,因为我是 Rust 和 WebAssembly 的新手。谁能发现我的错误?

最佳答案

到目前为止,Rust 中的 WebAssembly 后端似乎没有提供导入或导出(函数)table 的方法;索引 f 很好,但是 imports.env.tablewasm 实例(即空)使用的表不同。

此外,您应该在 FFI 中使用 extern fn

如果您想深入了解 Playground提供了一些不错的 WebAssembly 优化,看看这个例子:

Playground

#![crate_type = "cdylib"]
#![feature(link_args)]
#![allow(unused_attributes)] // link_args actually is used
#![link_args = "--import-memory"]

extern "C" {
fn peekaboo(f: extern "C" fn(u32) -> u32);
}

#[no_mangle]
pub fn run() {
extern "C" fn plus_one(x: u32) -> u32 {
x + 1
}

unsafe {
peekaboo(plus_one);
}
}

结果应该是这样的:

(module
(type $t0 (func))
(type $t1 (func (param i32) (result i32)))
(type $t2 (func (param i32)))
(import "env" "peekaboo" (func $peekaboo (type $t2)))
(import "env" "memory" (memory $env.memory 17))
(func $run (export "run") (type $t0)
(call $peekaboo
(i32.const 1)))
(func $playground::run::plus_one::h85275af105f0cc85 (type $t1) (param $p0 i32) (result i32)
(i32.add
(get_local $p0)
(i32.const 1)))
(table $T0 2 2 anyfunc)
(elem (i32.const 1) $playground::run::plus_one::h85275af105f0cc85))

如果你想在本地复制这个,将它添加到你的 Cargo.toml 中:

[lib]
crate-type = ["cdylib"]

[profile.release]
lto = true

并使用 cargo +nightly build --release --target wasm32-unknown-unknown 进行构建(假设 rustup 使用 nightly 工具链和 nightly 工具链启用的 wasm32-unknown-unknown 目标。

关于javascript - 如何解析 Rust 和 WebAssembly 中的函数指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47778074/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com