如何在 HashMap 中存储方法指针并调用它们
How to store method pointers in a HashMap and call them
我正在尝试编写一个 chip8 模拟器,但借用检查器让我很为难。
我的想法是通过在 HashMap
中查找方法指针然后执行该方法指针来解码操作码,但我无法使可变方法指针正常工作:
struct Chip8 {
opcode: u16,
//... other fields
jump_table: HashMap<u16, Box<fn(&mut Chip8)>>,
}
使用指针的函数:
fn execute_decoded(&mut self, key: u16) {
let func = self.jump_table.get(&key);
match func {
Some(func) => func(self),
None => {
println!("invalid op: {}", self.opcode);
sleep(Duration::from_millis(10000));
return;
}
}();
self.program_counter = self.program_counter + 2;
}
检查员抱怨:
cannot borrow `*self` as mutable because `self.jump_table` is also borrowed as immutable
--> main.rs:168:36
|
165 | let func = self.jump_table.get(&key);
| --------------- immutable borrow occurs here
...
168 | Some(func) => func(self),
| ^^^^ mutable borrow occurs here
...
178 | }
| - immutable borrow ends here
我不明白为什么会出现这个错误。
为什么要 self.jump_table.get(&key)
借钱?基于 execute_decoded
的签名,我假设它适用于 self
的可变借用版本,不需要额外借用。
Rust 中的 HashMap
拥有其中的所有内容。为了得到你的函数指针,你用 let func = self.jump_table.get(&key);
借用它。所以现在,func
是 不变地借用 self.jump_table
(这是 self
的一个元素)。
问题是您正试图将所有 self
传递给 func
。如果您不可变地传入 self
就没问题,因为您可以不可变地借用 self
任意多次。但是,由于您试图可变地借用 self
,编译器将不允许您这样做,因为您刚刚不变地借用了 self
的 部分 (特别是 self.jump_table
).
解决此问题的一种方法是将您的 Chip8
结构拆分为更小的结构,这样您就可以将所有必要的信息传递给 func
而无需传递 jump_table
.
没有理由 Box
HashMap
中的函数指针,这只会引入不必要的间接寻址。
与 一样,您正在借用函数指针。问题是,没有理由这样做。您可以只复制函数指针以将其与 HashMap
:
解除关联
use std::collections::HashMap;
struct Chip8 {
jump_table: HashMap<u16, fn(&mut Chip8)>,
}
impl Chip8 {
fn execute_decoded(&mut self, key: u16) {
let func = self.jump_table.get(&key).map(|x| *x);
match func {
Some(func) => func(self),
None => {
println!("invalid op");
}
};
}
}
fn main() {}
我正在尝试编写一个 chip8 模拟器,但借用检查器让我很为难。
我的想法是通过在 HashMap
中查找方法指针然后执行该方法指针来解码操作码,但我无法使可变方法指针正常工作:
struct Chip8 {
opcode: u16,
//... other fields
jump_table: HashMap<u16, Box<fn(&mut Chip8)>>,
}
使用指针的函数:
fn execute_decoded(&mut self, key: u16) {
let func = self.jump_table.get(&key);
match func {
Some(func) => func(self),
None => {
println!("invalid op: {}", self.opcode);
sleep(Duration::from_millis(10000));
return;
}
}();
self.program_counter = self.program_counter + 2;
}
检查员抱怨:
cannot borrow `*self` as mutable because `self.jump_table` is also borrowed as immutable
--> main.rs:168:36
|
165 | let func = self.jump_table.get(&key);
| --------------- immutable borrow occurs here
...
168 | Some(func) => func(self),
| ^^^^ mutable borrow occurs here
...
178 | }
| - immutable borrow ends here
我不明白为什么会出现这个错误。
为什么要 self.jump_table.get(&key)
借钱?基于 execute_decoded
的签名,我假设它适用于 self
的可变借用版本,不需要额外借用。
Rust 中的 HashMap
拥有其中的所有内容。为了得到你的函数指针,你用 let func = self.jump_table.get(&key);
借用它。所以现在,func
是 不变地借用 self.jump_table
(这是 self
的一个元素)。
问题是您正试图将所有 self
传递给 func
。如果您不可变地传入 self
就没问题,因为您可以不可变地借用 self
任意多次。但是,由于您试图可变地借用 self
,编译器将不允许您这样做,因为您刚刚不变地借用了 self
的 部分 (特别是 self.jump_table
).
解决此问题的一种方法是将您的 Chip8
结构拆分为更小的结构,这样您就可以将所有必要的信息传递给 func
而无需传递 jump_table
.
没有理由 Box
HashMap
中的函数指针,这只会引入不必要的间接寻址。
与 HashMap
:
use std::collections::HashMap;
struct Chip8 {
jump_table: HashMap<u16, fn(&mut Chip8)>,
}
impl Chip8 {
fn execute_decoded(&mut self, key: u16) {
let func = self.jump_table.get(&key).map(|x| *x);
match func {
Some(func) => func(self),
None => {
println!("invalid op");
}
};
}
}
fn main() {}