6 ms·
I've thought alot about this before. Rust doesn't really have very great interoperability with C - most languages really don't, because the API for C programs r
by DSMan195276 10y ago
I've thought alot about this before. Rust doesn't really have very great interoperability with C - most languages really don't, because the API for C programs revolves around functions, structs, macros, etc. Most languages can only really get part of that, and then the rest gets essentially a separate implementation in the language you're porting too - leading to a certain amount of manual duplication and intervention necessary (We don't call it porting when you use a C library in C). Design goals Rust has made compound the issue a bit more: For example, Rust uses the C++ ABI, not C. Rust can't generally use header files directly. The Rust<->C conversion loses a lot of information and can result in fairly messy code by Rust standards, etc.
This makes combining Rust into already existing C code a hassle, as it is generally worse then even just trying to use C and C++ together which is already fairly annoying and error-prone. This is compounded by Rust's safety goals which generally require a different design to a problem then the "C-style" approach would be - IE. You're probably not going to get good Rust code by simply replacing a .c file with a Rust file, because the entire time you're going to have to make use of the unsafe C functions that your program includes.
Perhaps the bottom line is that (for good reason) Rust is much more then just an improved C. And because of that, combining C and Rust is always going to feel like combining two separate systems together with a compatibility layer in-between - because that's really what it is - and that's just not very attractive.
I know little about Zig (I'm reading about it for the first time now) and don't at all predict it to replace C. That said, I would love a language which has a focus on maintaining very good compatibility with C while fixing the various pieces of its design that are fixable within the bounds of the language. For example, I noticed it mentioned in the README that in Zig that pointers are nonnull by default, and can be made nullable by adding the 'maybe' attribute. This is a feature I would love in C, but really isn't there (gcc has a nonnull attribute, but it is really essentially useless and nothing like you'd want). Essentially, I would like a language where it feels like writing code for the same system, but in a different (better) syntax - where I can drop it into a project and it works together with the system like any other .c file (Though with a different compiler, obviously), but the code inside is much better then what you can do in standard C. I think that such a language could retain the reasons why people (like me) still like C, while fixing a lot of the uglier sides to the language that everybody is aware of but aren't going to get fixed any time soon. And perhaps most importantly, I think such a language is definitely possible (Though it may not be able to employ all the features you may want) - but I don't have the time nor probably the skills to really do it well besides list off the things it should fix and shouldn't fix.
As for starting a project though, if you ignore difficulty to learn then I would agree with you: There's probably little reason not to just go for Rust if you're already willing to learn a new language. For most projects the issues I outlined above don't really matter assuming the entire project is written in Rust - besides the want for a language closer to C in design. That said, I readily concede that I have no idea if Rust's borrow-checking semantics could ever work without the extra features they added that take the design away from being 'C-like' - and considering that's one of the definitive features of Rust, is easily worth losing the 'C-like' detail if it is necessary.
But when considering a project like the Linux Kernel, the GNU coreutils, git, GTK, and other various large projects where conversion to Rust is probably impossible without a complete rewrite, being able to use a 'better' C while still retaining the aspects that people like would probably be a nice step in the right direction. The chances of it happening are nil, but it would still be a step in the right direction.
- steveklabnik 10y ago> ust uses the C++ ABI, not C. Rust uses its own ABI, not any of the various C++ ones. Our strategy for interop with C is two-fold: first, a very thin, direct wrapper. These are the various *-sys packages. They know how to link in (and maybe even build!) the underlying C library, and provide functions you can call from Rust. Then, on top, people can write a more idiomatic Rust wrapper, working in Rust's safety guarantees. That takes some work and time to get right, but hopefully, it means that in the end, Rust users of C libraries shouldn't have to deal with the stuff you're talking about.
- DSMan195276 10y agoYou're 100% right. I was actually thinking of name-mangling when typing that, but that's still not quite right. The point I was trying (and failing) to make is that Rust uses things like name-mangling and a different ABI that makes interop more of a challenge - similar in challenge to interop with C++ from C. C technically has name-mangling too, but generally speaking either there is no mangling at all, or they just add an '_' to every symbol name. Edit: To address your second point, I think that is a step in the right direction - and I think that Rust's compatibility with C libraries is probably fine, and comparable to most languages. I don't consider that to be so big of a turn-off that I wouldn't want to use Rust for a new project, though obvious writing wrappers isn't always fun or error-free. But, assuming I'm understanding what you're getting at correctly, I'm not sure that will really solve the core problem I'm trying to get at: Generally speaking, nobody wants to be maintaining compatibility wrappers for APIs that exist entirely within their program and are probably changing all the time, and that's really what you need if you want to replacing part of a C program with Rust. For example, to take it to the 'extreme' - the Linux Kernel module API changes virtually every version of the kernel (And the ABI is not guaranteed at all), and maintaining a complete Rust wrapper for it would not be a fun time even if a certain amount of it can be auto-generated. The API includes a very complicated mess of functions, inline functions, macros, structures (with varying different types of alignment and padding). None of it is guaranteed to stay the same across versions. And I think it is fair to say that most C programs have internal APIs like this (Though not as crazy) that are changing all the time and not intended to be seen by the 'outside world'. It's these types of things that I see being a problem for interfacing with Rust - APIs that are changing all the time in complicated ways which make writing and maintaining a wrapper very annoying and error-prone.