How to implement a C++ method pointer or C# delegate

Hello -

Completely new to Rust but very interested if there is a way to implement something like a C++ pointer to a method on an object (not a function!). In C# Delegates work in a similar manner.

I am somewhat suspecting Box might be involved or possibly some approach with enums. This may give some idea of what I'm hoping to achieve:

struct Machine {
    state: %% whatever type will reference either Machine::S1 or Machine::S2 %%,
}

impl Machine {
    fn new() -> Machine {
        Machine {
            state: Machine::S1, // init state to point to S1
        }
    }
    
    fn S1(&mut self) {}

    fn S2(&mut self) {}
    
    fn transitionToS2(&mut self) {
        self.state = self.S2;      // dynamically change state to point to S2
    }
}

fn main() {
    let mut m = Machine::new();
    m.transitionToS2();
}

Thank you

A function pointer type looks like this:

state: fn(&mut Machine)

You can call it like this:

fn run_state(&mut self) {
    (self.state)(self)
}

Complete example in Playground.

Note: A function pointer in Rust is similar to a function pointer in C or C++; it cannot capture variables or "bind" its arguments. If you want something closer to C# delegates or lambdas, you will want to use closures stored as trait objects.

Thanks very much for the reply. Will the closures be able to make mutable changes on the object's state? Including updating the state variable to another closure? I'm still unsure about the scoping rules for closures and thought they might not be able to make mutable changes to the Machine object.

Thanks

You can build a closure that holds a mutable reference to a Machine, but the borrowing rules won’t let you store it as a field inside that structure. The easiest way around this is to accept the mutable reference as an argument, like the function pointer solution does.

An alternative is to use Rc<Machine> and then store the state as something like RefCell<Option<Box<dyn Fn()>>>, but you’ll need to do some gymnastics to not hold the cell’s lock while the function is executing.

1 Like

Your code was what I needed - thanks very much for the help.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.