Async-ffi crate for c# async calls

Hi, I'm going to have to learn c# for a project soon, but I still want to use some Rust code in the project via a shared library (.dll / .so). Some of these function calls will have to be async, and I was wondering if the following crate would allow async calls from c#:

I don't know a lot about c# yet, but it would be nice to know ahead of time if this crate would work and if not, is there a different solution to my problem?

This crate doesn't seem to be meant for cross-language usage. It allow to send async function across ffi boundaries but it should only be usable from Rust. The intent is to allow to share an async rust library as an .so and avoid having to share source code as well without the concern to use exact same version of Rust for the client as the one used to build the library.

So this crate seem to be more oriented to provide async functions to external clients using Rust for which you don't want to share your code with. It won't help you much here.

Async needs some runtime to work (you will have to register for events, and you'll block a thread for polling new events, and much more...) and these are generally not portable. I don't think you'll find easy way to send a Rust Future and make it run by C# async runtime.

The solution in my opinion is :

  • export all your functions as extern "C" functions
  • one function is used to initialise your library, this will spawn a new thread where you'll run your async event loop (using mio, tokio, async-std, ...), create some communication means to be able to send commands to this loop using channels, and send back an opaque pointer which is obtained from a Box<T> where T is a struct where you store all the data you need to communicate with async thread (the sender side of the channel, maybe sender of another channel to send a stop signal,..)
  • all exported "async" functions are normal extern "C" functions which takes the opaque pointer, a callback and the required parameters. This will send a command to the async thread and callback should be called when this specific function is over.
  • on your C# side, you can write a wrapper to translate these into C# async functions. I do not know async C#, it seems that Task are equivalent to Rust Future, so you would return a task that would be marked as completed when the callback is received. (The extern "C" functions exported from Rust should accept an opaque pointer as a "userdata" parameter, this would be forwarded as a parameter to the callback, allowing to add some state in these callbacks and find which Task to complete)

Hope I'm clear and this would help :slight_smile: