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.
That strategy is also used by Haskell, what typically happens is that the idiomatic wrapper ends up being out of date, poorly documented and if the library is prominent enough there might be even several competing ones.
You'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.
Oh, and to reply to your edit: yes, writing a wrapper for an unstable interface isn't exactly fun. But that also means that your C code is going to have to update with each release too, an unstable API is unstable for everyone.
A C API can stay relatively the same if you switch a function to a macro, or make it inline. In a lot of cases you don't actually care which of the options it might be to begin with - the syntax generally stays the same, and the situations where you care (Mostly just function pointers) are somewhat uncommon. Such changes would easily break a simple wrapper though. That said I do see your point - It's not like the C code is guaranteed to work either, so perhaps that is acceptable. The maintainer still has to weigh the disadvantages of supporting a Rust wrapper to the advantages of allowing Rust code.
My original point (which has gotten a bit muddled in the details) was just that there could be room for a language closer to C that offers to fix some of the more annoying issues, while still keeping very good compatibility with C overall and avoiding the need for 'wrappers' and such to interface it with C code.
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.