Rust FFI crates?

What are the essential/popular crates that provide types, traits, utility functions and macros for general FFI work? Is there a crate that gathers them together for a "batteries included" Rust FFI environment?

Do you mean something like the libc-crate?

Sure that's useful for basic types. But I was more thinking of crates that help writing an interface to C libraries or exporting a C API (as C is the de facto standard for interop).

For example, dealing with bitfields, C's enums, function pointers, opaque data types, etc. I feel like I'm writing a lot of boilerplate that other people must have done better than I can.

It would be very interesting to see something like this. What I've found in my own work is that I end up creating a lot of macros to perform common operations. These macros so far have all been pretty specific to each crate I'm building and interface for.

Thinking about this some more it would be great if there was a reference for implementing C types and patterns for different FFI scenarios.

I'm slowly building up some knowledge in this area but I'm still quite new to the language.

Do you mean bindings (i.e. extern "C" declarations) or wrappers (i.e. a rustier API)? To make bindings in rust for a C library, bindgen should be your go-to solution.

As for wrappers? Yeah, that's kind of tough to solve generally, because it requires designing a new API. :stuck_out_tongue:

Yep I'm more thinking of wrappers rather than just the extern bits. In my (very limited) experience bindgen is a bit "dumb" when it comes to types. Which is understandable because C code has pretty weak typing and even namespacing is mostly done by various conventions.

If bingen could understand the API docs as well as the code, there'd be a lot less for me to do! :stuck_out_tongue:

We ended up writing something like this when trying to use a Rust library from a GUI application at work. It's published as the ffi_helpers crate and involves:

  • A C-style error-handling mechanism, mostly based upon errno which is used all over the place in Linux
  • A helper trait and macro for working with Nullable values, letting you set the error code and return early from a function when a null pointer is detected
  • Making sure a piece of code is exception safe (i.e. std::panic::catch_panic()), allowing you to set the error code and return an "obviously invalid" value (usually null)
  • A mechanism for executing a long-running Rust task on a background thread, with the ability to periodically poll for a result or tell the task to cancel early. The really neat part about this is you just need to implement a Task trait then there's a macro which will generate all the extern "C" functions necessary for spawning the task and managing it.

I'm slowly working on rewriting my Rust FFI Guide to help people learn this sort of stuff. The work-in-progress document is available online. Let me know if it's useful or there are bits which can be improved. My goal is that one day it'll be part of the Rust bookshelf, but I wouldn't say the guide is ready for human consumption just yet.

2 Likes

Thanks, that's the sort of thing I'm looking for. I find the error handling and Nullable especially interesting. And you guide may not be finished yet but it does contain ideas I'm finding useful, so thanks.

Has anything happend in this space? I was just looking for this same thing.