4 ms·
Ask HN: Do you have experience converting a C library to Rust?
I'm curious what my options are for converting a C library to Rust if a) I want it to maintain the same external interface and b) I don't want to do all the work of converting upfront. Is there anything to be aware of for a codebase that's half Rust, half C? Is the only option for interop using C FFI in Rust?
- db48x 8y agoThe general strategy is to port one function to Rust at a time. At first those functions would be called from C and would call functions written in C, but the more you port the more your Rust functions would be calling other Rust functions, so the more scope you would have for using advanced Rust features like generics, traits, enums, etc.
- swingline-747 8y agoI was just talking to someone about this. The docs describe the fn call interface here: https://doc.rust-lang.org/book/second-edition/ch19-01-unsafe-rust.html#using-extern-functions-to-call-external-code https://doc.rust-lang.org/book/second-edition/ch19-01-unsafe... Then you need a .h header. I would include a .la and .pc so other toolchains can set their options correctly. The build instructions for users would be something like cargo build or make (which calls cargo). PS: Mozilla does ;)
- swingline-747 8y agoAlso a recent RustConf video on the topic https://youtu.be/x9acx2zgx4Q https://youtu.be/x9acx2zgx4Q
- swingline-747 8y agoAlso, as mentioned, here's a C to Rust transpiler funded by DARPA to help with migrations https://c2rust.com/ https://c2rust.com/ RustConf video https://youtu.be/WEsR0Vv7jhg https://youtu.be/WEsR0Vv7jhg it uses clang and bindgen under the hood
- spease 8y agoThere are a few automotated solutions (eg corrode, c2rust, etc) that others will undoubtedly mention. These should help with (b). You can use bindgen to generate Rust bindings for a C library given a header file. You can use cheddar to generate a C header file for Rust code with extern fns. This should help with (a). So you could set up cheddar, then use bindgen to generate functions which call the original c library. At this point all the Rust code will be doing is generating a (hopefully) functionally identical header file for a Rust library that calls the C library. Then you could run automated tools on the library to generate Rust functions and move things over function by function. Starting with the functions that are at the bottom of the dependency tree. Rust has no significant runtime, no garbage collection, and is intended to run as fast as C (if you notice any significant deviations, complain on the irc channel, mailing list, or /r/Rust subreddit). So it should be reasonably straightforward as long as the C is well formed and you don’t introduce any stale/null pointer dereferences. Does that make sense? EDIT: Also note that there’s a gcc crate you can use to actually build a C library from source using a Rust buildscript. Depending on how you do things, you might find it useful.