首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用wasm-bindgen对大型锈菌对象进行Js绑定

用wasm-bindgen对大型锈菌对象进行Js绑定
EN

Stack Overflow用户
提问于 2020-12-10 21:06:57
回答 2查看 899关注 0票数 1

我想编写一个vscode扩展名,它显示用bincode编写的大型二进制文件的内容。

代码语言:javascript
复制
#[macro_use]
extern crate serde_derive;

use std::collections::HashMap;
use std::fs::File;
use std::io::{BufReader, BufWriter};

#[derive(Serialize, Deserialize)]
pub struct MyValue {
    pub name: String,
}

#[derive(Serialize, Deserialize)]
pub struct MyStruct {
    pub data: HashMap<String, MyValue>,
}

impl MyStruct {
    pub fn dump(&self, filename: &str) -> Result<(), String> {
        let file = File::create(filename).map_err(|msg| msg.to_string())?;
        let writer = BufWriter::new(file);
        bincode::serialize_into(writer, self).map_err(|msg| msg.to_string())
    }

    pub fn load(filename: &str) -> Result<Self, String> {
        let file = File::open(filename).map_err(|msg| msg.to_string())?;
        let reader = BufReader::new(file);
        bincode::deserialize_from::<BufReader<_>, Self>(reader).map_err(|msg| msg.to_string())
    }
}

因此,有一个黄蜂绑定:

代码语言:javascript
复制
#[wasm_bindgen]
#[derive(Clone)]
pub struct PyMyStruct {
    inner: Arc<MyStruct>,
}

#[wasm_bindgen]
impl PyMyStruct {
    pub fn new(filename: &str) -> Self {
        Self {
            inner: Arc::new(MyStruct::load(filename).unwrap()),
        }
    }

    pub fn header(self) -> Array {
        let keys = Array::new();
        for key in self.inner.data.keys() {
            keys.push(&JsValue::from_str(key));
        }
        keys
    }

    pub fn value(&self, name: &str) -> JsValue {
        if let Some(value) = self.inner.data.get(name) {
            JsValue::from_serde(value).unwrap_or(JsValue::NULL)
        } else {
            JsValue::NULL
        }
    }
}

它为JavaScript世界提供了一个简单的接口,以便访问该文件的内容。使用Arc,以防止在JavaScript端处理时昂贵的意外内存复制。( keys不被标记为可变,但锈蚀编译器却以这种方式重复使用,这看上去可能很奇怪)

运行测试代码时:

代码语言:javascript
复制
const {PyMyStruct} = require("./corejs.js");

let obj = new PyMyStruct("../../dump.spb")
console.log(obj.header())

您将得到错误消息:

错误:空指针传递给锈病

有人知道如何处理这个用例吗?

谢谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-12-11 12:34:53

我通过使用https://neon-bindings.com来解决这个问题,而不是将API编译到web程序集中。

此处的绑定如下:

代码语言:javascript
复制
use core;
use std::rc::Rc;
use neon::prelude::*;

#[derive(Clone)]
pub struct MyStruct {
    inner: Rc<core::MyStruct>,
}

declare_types! {
    pub class JsMyStruct for MyStruct {
        init(mut cx) {
            let filename = cx.argument::<JsString>(0)?.value();

            match core::MyStruct::load(&filename) {
                Ok(inner) => return Ok(MyStruct{
                    inner: Rc::new(inner)
                }),
                Err(msg) => {
                    panic!("{}", msg)
                }
            }
        }

        method header(mut cx) {
            let this = cx.this();
            let container = {
                let guard = cx.lock();
                let this = this.borrow(&guard);
                (*this).clone()
            };
            let keys = container.inner.data.keys().collect::<Vec<_>>();
            let js_array = JsArray::new(&mut cx, keys.len() as u32);
            for (i, obj) in keys.into_iter().enumerate() {
                let js_string = cx.string(obj);
                js_array.set(&mut cx, i as u32, js_string).unwrap();
            }
            Ok(js_array.upcast())
        }

        method value(mut cx) {
            let key = cx.argument::<JsString>(0)?.value();
            let this = cx.this();
            let container = {
                let guard = cx.lock();
                let this = this.borrow(&guard);
                (*this).clone()
            };
            if let Some(data) = container.inner.data.get(&key) {
                return Ok(neon_serde::to_value(&mut cx, data)?);
            } else {
                panic!("No value for key \"{}\" available", key);
            }
        }
    }
}

register_module!(mut m, {
    m.export_class::<JsMyStruct>("MyStruct")?;
    Ok(())
});
票数 0
EN

Stack Overflow用户

发布于 2020-12-10 23:02:15

这里的问题是您使用的是new PyMyStruct()而不是PyMyStruct.new()。在wasm-bindgen的调试模式中,您将在运行时得到一个错误。使用.new()将解决您的问题:

代码语言:javascript
复制
let obj = PyMyStruct.new("../../dump.spb")

如果将#[wasm_bindgen(constructor)]注释添加到new方法中,那么new PyMyStruct()也会工作:

代码语言:javascript
复制
#[wasm_bindgen]
impl PyMyStruct {
    #[wasm_bindgen(constructor)]
    pub fn new(filename: &str) -> Self {
        Self {
            inner: 1,
        }
    }
}

现在,这很好:

代码语言:javascript
复制
let obj = new PyMyStruct("../../dump.spb")
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65242336

复制
相关文章

相似问题

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