我可以将闭包序列化为 Vec<u8> 然后反序列化并执行它吗?

我想做这样的伪代码:

let mut vec = Vec<u8>::new();
vec.resize(1024); // Some large-enough size

serialize(&vec,|| { .... });

// ... other code blah blah ...

deserialize(&vec); // This will execute the closure

理想情况下,我可以在另一个线程中运行反序列化,这才是真正做到这一点的重点。

我不想发送操作码和数据,因为这种方式打开了一个非常干净的编程模型,您无需创建和发送消息。相反,您只需在另一个线程中运行任意复杂的代码。

为什么“非常干净”?

  1. 没有需要创建的操作码(消息)。即,更少的代码。

  2. 接收端没有操作码调度的switch语句。即,更少的代码。

  3. 因为没有协议,所以没有必要对消息进行版本控制。即,更少的代码。

这个想法不能跨进程使用,但可以满足我的需求。

fatglen 回答:我可以将闭包序列化为 Vec<u8> 然后反序列化并执行它吗?

不使用unsafe?不不不不。

问题在于,由于 Vec<u8> 可以被微不足道地修改,因此您很容易违反 Rust 的安全不变量。考虑以下代码:

let vec = Vec<u8>::new();
vec.resize(1024);
// Our theoretical serialize function.
serialize(&vec,|| { /* ... */ });
vec[0] = 0x90; // What happens to the closure now?
deserialize(&vec); // There goes any memory safety...

但是,如果您只想在线程之间发送闭包,请考虑使用诸如 std::sync::mpsc 之类的东西,它支持发送闭包:

use std::thread;
use std::sync::mpsc::channel;

let (tx,rx) = channel();
thread::spawn(move || {
    tx.send(|| { "hi" }).unwrap();
});
let f = rx.recv().unwrap();
assert_eq!(f(),"hi");

然而,我的猜测是,这实际上不是您想要做的。就像 Netwave 在评论中所说的那样,您很可能实际上想要发送数据和操作的标签;例如:

// On one thread...
tx.send((Op::REMOVE_FILE,path));
// and on the other thread...
let (op,path) = rx.recv();
match op {
  Op::REMOVE_FILE => remove_file(path),/* ... */
}
本文链接:https://www.f2er.com/35690.html

大家都在问