11

I've had a look over the rust foreign function interface, and successfully (and happily) can call a c library from my rust code.

However, I can't seem to find any details on how to register a callback to invoke rust code, from within the c-code scope.

Is this even possible?

As a justification for 'why would you even do that?'; specifically I'm looking at embedding either lua or python in a rust application, and exposing a scripting-api for scripts that run on the embedded runtime.

Invoking these would be something along the lines of:

  • Main rust application loads
  • Application uses ffi to initialize the scripting runtime
  • Application binds local rust functions to C-callbacks
  • Application invokes ffi to bind the C-callbacks to the scripting layer
  • Application runs~
  • Periodically ffi is used to trigger the scripting runtime to execute blocks of bytecode
  • The scripting code does various trivial logic and calls bound handles
  • The bound handles invoke the c code
  • The bound c code invokes local rust code

All of these steps except for the ones in bold I've managed to get working, and I've done some trivial work using a scheduler, which the C-callbacks dump 'run me' commands into a queue and when control returns to the rust scope, the application queries the queue and runs the commands in it...

...but it's a little awkward from the scripting side, because it means multiple nested async callbacks, and the point of the scripting layer is to simplify the code that needs to go into the scripting layer.

1 Answer 1

12

Yes, you can pass a callback function from Rust to C and invoke it there. The main thing to know is that you have to define the function with the extern "C" attribute.

Untested example (no Rust compiler here):

Rust side:

extern "C" fn callback(a:i32) {
    println!("I'm called from C with value {0}", a);
}

#[link(name = "mylib")]
extern {
   fn register_callback(cb: extern "C" fn(i32)) -> i32;
}

fn main() {
    unsafe {
        register_callback(callback);
    }
    ...
}

C side:

typedef void (*rust_callback)(int32_t);
rust_callback cb;

int32_t register_callback(rust_callback callback) {
    cb = callback;
    return 1;
}

void thread() {
  // do sth
  cb(xyz);
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.