'How can i pass a struct method as callback in Rust?
In C++, I work with this.
class A{
public:
void read();
}
class B{
public:
void setCallback(std::function<void()> f){
...
}
}
int main(){
A a;
B b;
b.setCallback(std::bind(&A::read,&a));
}
Could I implement the same function in Rust?
Solution 1:[1]
@isaactfa answer is correct, but std::function uses dynamic dispatch and is more like Box<dyn Fn()> than using generics.
struct B<'a> {
callback: Option<Box<dyn FnMut() + 'a>>,
}
impl<'a> B<'a> {
fn set_callback(&mut self, callback: Box<dyn FnMut() + 'a>) {
self.callback = Some(callback);
}
fn call_callback(&mut self) {
self.callback.as_mut().map(|cb| cb());
}
}
fn main() {
let mut a = A { x: 0 };
let mut b = B { callback: None };
b.set_callback(Box::new(|| a.do_something()));
b.call_callback();
drop(b); // It is necessary for the code to not use `a` while it's borrowed by the closure
assert_eq!(a.x, 1);
}
You can have a little more convenience by creating the Box within the struct methods, so the caller doesn't have to create it:
impl<'a> B<'a> {
fn set_callback(&mut self, callback: impl FnMut() + 'a) {
self.callback = Some(Box::new(callback));
}
}
Solution 2:[2]
Does this work for you?
struct A {
x: u32,
}
impl A {
fn do_something(&mut self) {
self.x += 1;
}
}
struct B<F> {
callback: Option<F>,
}
impl<F: FnMut()> B<F> {
fn set_callback(&mut self, callback: F) {
self.callback = Some(callback);
}
fn call_callback(&mut self) {
self.callback.as_mut().map(|cb| cb());
}
}
fn main() {
let mut a = A { x: 0, };
let mut b = B { callback: None, };
b.set_callback(|| a.do_something());
b.call_callback();
assert_eq!(a.x, 1);
}
I took a conservative guess at what the mutability requirements would be.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Chayim Friedman |
| Solution 2 | isaactfa |
