Back to async task from ffi

Hi!

I'm calling into C code from a LocalPool executor. Then in the C code I can also call back into Rust code (still running in the same async task). Can I somehow convince the compiler that I'm still in the async task context so I can do .await when calling back into Rust code?

You can't do that directly, because async code that can use .await is not a regular code that "runs", but a state machine built by the compiler and expressed as a Future object. C has no idea what that is, so it won't transform itself into a compatible kind of re-entrant state machine.

If C only calls into async Rust, but doesn't need to see the result or wait for it to run, then it can make the call. You will have to wrap the result of the call in BoxFuture, which you give back to C, and which C will give back to the async Rust function which called it, and then the async function can .await it.

If you can change the C code to be split into two parts: before the async call, and after the async call, then you can make C return control back to Rust, have Rust wait for whatever async operation you need, and have Rust call C again with the result.

If C expects to call synchronous blocking callback, then you have no choice but to make Rust code it calls synchronous blocking code. You may need to spawn the call to C on a separate thread with spawn_blocking (so that C can block the thread while waiting), and then in Rust callback use things like handle.block_on(future) to wait for an async operation.

4 Likes

Thanks for an excellent answer! Not sure which approach would be best. I have to noodle on it.

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.