我最近创建了一个工具,它允许我从代码中的任何位置访问结构,只需通过结构名称。 它的工作方式非常简单,分配足够的空间来保存所需的结构,并存储指向每个结构的指针,并通过取消引用来访问它们。
#[derive(Debug, Default, Module)]
pub struct SomeStruct {
test_u8: u8,
test_vec: Vec<u8>,
}
#[derive(Debug, Default, Module)]
pub struct OtherStruct {
pub test_vec: Vec<u8>,
}
fn main() {
let bundle = ModuleBundleBuilder::default()
.add_module::<SomeStruct>()
.add_module::<OtherStruct>()
.build()
.unwrap();
module_manager::init(bundle);
let other_struct = get_module_mut::<OtherStruct>();
other_struct.test_vec = Vec::new();
other_struct.test_vec.push(2);
other_struct.test_u8 = 2;
dbg!(&other_struct.test_vec.as_ptr());
//[app/src/main.rs:25:5] &other_struct.test_vec.as_ptr() = 0x000058ff06362c50
get_module_mut::<SomeStruct>().test_vec = Vec::new();
dbg!(&other_struct.test_vec.as_ptr());
//[app/src/main.rs:27:5] &other_struct.test_vec.as_ptr() = 0x0000000000000001
dbg!(&other_struct.test_u8);
//[app/src/main.rs:30:5] &other_struct.test_u8 = 2
}
当我在单个包中使用上面的示例时,它工作得非常好。当我开始使用工作区并在工作区的不同成员中定义任一结构时,就会出现问题。 正如示例中所示,当我有两个结构体,每个结构体都持有一个 Vec 时,当我对其中一个结构体进行变异时,另一个结构体就会被丢弃或清除。
此时,我对如何解决该问题没有任何想法,希望这不是 Rust 本身的限制或错误。该工具位于 crates.io 上,称为模块管理器。
如果有人能给我建议一个解决方案,我会非常高兴。
你正在使用的这个库(
module_manager
)充满了UB和不健全之处。不要使用它。
您可以通过以下简单安全的代码实现您想要的:
use std::any::{Any, TypeId};
use std::cell::{Ref, RefCell, RefMut};
use std::collections::HashMap;
pub struct ModuleBundle {
map: HashMap<TypeId, RefCell<Box<dyn Any>>>,
}
impl ModuleBundle {
pub fn new() -> Self {
Self {
map: HashMap::new(),
}
}
pub fn add_module<M: Any>(&mut self, module: M) {
self.map
.insert(TypeId::of::<M>(), RefCell::new(Box::new(module)));
}
pub fn get_module<M: Any>(&self) -> Option<Ref<'_, M>> {
self.map.get(&TypeId::of::<M>()).map(|module| {
Ref::map(module.borrow(), |module| {
module.downcast_ref::<M>().unwrap()
})
})
}
pub fn get_module_mut<M: Any>(&self) -> Option<RefMut<'_, M>> {
self.map.get(&TypeId::of::<M>()).map(|module| {
RefMut::map(module.borrow_mut(), |module| {
module.downcast_mut::<M>().unwrap()
})
})
}
}
这不允许您按照 Rust 定律的要求两次可变地获取模块。