ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

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

2019-11-10 18:34:19  阅读:462  来源: 互联网

标签:webassembly rust shared-memory javascript pointers


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

初始化此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后端似乎还没有提供导入或导出(功能)表的方式;索引f很好,但是import.env.table与wasm实例使用的表不同(即为空).

另外,您应该在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

并使用每晚构建货物–release –target wasm32-unknown-unknown进行构建(假设使用夜间工具链的rustup设置和为夜间工具链启用的wasm32-unknown-unknown目标).

标签:webassembly,rust,shared-memory,javascript,pointers
来源: https://codeday.me/bug/20191110/2014338.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有