【问题标题】:Access Impl field from closure before field is alloc'ed in Rust?在 Rust 中分配字段之前从闭包访问 Impl 字段?
【发布时间】:2022-01-04 07:21:41
【问题描述】:

我是 Rust 新手,这可能很明显。

基本上我有这个场景,你可以在下面看到,我创建了一个添加了闭包的新类型,但是这个闭包需要访问尚未创建的数据。数据将在调用闭包时创建,但在最初创建闭包时,数据尚不可用。

最好的处理方法是什么?

如果我的闭包不是闭包,而是我的实现中的私有函数,我也很好奇,我将如何访问该数据?这个闭包/函数是来自 WasmTime 的回调,需要一个明确的方法签名,它不允许我添加 $self 到它。那么如何在函数参数中不引用 $self 的情况下获取实现的实例字段呢?

pub struct EmWasmNode {
    wasmStore: Store<WasiCtx>,
    wasmTable: Table,
}

impl EmWasmNode {
    pub fn new(filePath: &str) -> Result<Self> {

        let engine = Engine::default();
        // let module = Module::from_file(&engine, "wasm/index.wast")?;
        let module = Module::from_file(&engine, filePath)?;
        let mut linker = Linker::new(&engine);
        wasmtime_wasi::add_to_linker(&mut linker, |s| s)?;

        let wasi = WasiCtxBuilder::new()
            .inherit_stdio()
            .inherit_args()?
            .build();
        let mut store = Store::new(&engine, wasi);

        linker.func_wrap("env", "emscripten_set_main_loop", |p0: i32, p1: i32, p2: i32| {
            println!("emscripten_set_main_loop {} {} {}", p0, p1, p2);
/*** How would I access wasmTable and wasmStore from here to execute more methods??? ***/

            //let browserIterationFuncOption:Option<wasmtime::Val> = Self::wasmTable.get(&mut Self::wasmStore, p0 as u32);
            // browserIterationFuncOption.unwrap().unwrap_funcref().call(&store, ());
        })?;

        let instance = linker.instantiate(&mut store, &module)?;

        let table = instance
            .get_export(&mut store, "__indirect_function_table")
            .as_ref()
            .and_then(extern_table)
            .cloned();

        let start = instance.get_typed_func::<(), (), _>(&mut store, "_start")?;

        start.call(&mut store, ())?;

        Ok(EmWasmNode {
            wasmStore: store,
            wasmTable: table.unwrap(),
        })
    }

【问题讨论】:

  • 您是否检查过您使用的库在其文档中是否有类似的示例?
  • 你为什么不试试let table = RefCell::new(Option::None)?对我来说,这似乎是最简单的安全解决方案。
  • 我之前尝试过,但后来我遇到了如何将 ref 放入闭包的问题?如果更改它以使该方法将 &self 作为参数并在闭包内调用 &self.wasmTable 它会出错:“实现Fn 的要求从这里派生闭包是FnOnce 因为它将变量self 移出其环境"
  • 嗯,所以我把 let wasmTable = &self.wasmTable;封闭内。这意味着闭包捕获了一个引用并且我认为不会移动它?现在我收到一个错误,闭包需要:'类型必须满足静态生命周期'

标签: rust webassembly wasmtime


【解决方案1】:

你必须先实例化一个结构。我建议下面更简单的代码来看看我的想法。

struct Atype
{
    name: String,
}

impl Atype
{
    pub fn new() -> Self
    {
        Self{ name: String::from("zeppi")}
    }
    
    pub fn test(&self) -> ()
    {
        let func = | x | { println!("{} {}", &self.name, x);};
        func(3)
    }
}

fn main() {
    let o = Atype::new();
    o.test();
}

【讨论】:

  • 在我的情况下,'name: string' 的数据在 new() 方法中将不可用。该 var 必须在随后的方法调用中填充。处理这种情况的最佳方法是什么?使其成为 Some 或其他类型?还是完全有更好的方法?
  • "new" 就像一个静态方法,在 Java 或其他语言中,并且像方法一样测试。你必须工作两次。你可以像这样gist.github.com/zeppi/9a876a53595c1439b7eb35162b0b7fac
  • 感谢您到目前为止的帮助,但我认为它并不能完全解决我的问题。我已经编辑了您的要点,以尝试更好地解释我最初发布的代码遇到的问题。 gist.github.com/rygo6/c1e20c9ce879a5a5e0bde885a0f20230 基本上,闭包需要访问在创建闭包之前无法知道的数据。在 C++ 中,闭包只会指向创建时堆上的一些空内存。
猜你喜欢
  • 2015-07-06
  • 2022-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-03
  • 2022-07-13
  • 2014-10-23
  • 1970-01-01
相关资源
最近更新 更多