4 ms·
I have found Rust's C++ story better than most. C++ is unfortunately a hard language to interoperate with. Rust's C story is absolutely unparalleled, and an eas
by ilovecaching 8y ago
I have found Rust's C++ story better than most. C++ is unfortunately a hard language to interoperate with. Rust's C story is absolutely unparalleled, and an easy to way to share code between the two languages.
- ridiculous_fish 8y agoStrange comment, since C++'s "C story" is better than Rust's C story. (ObjC too.) As for C++ interop, ObjC++ is the best I've seen; is there something better?
- ilovecaching 8y agoI disagree. Rust has managed to have great interoperability, but hasn't made the sacrifice of backwards compatibility that has plagued C++. C++ is also ever so slightly different, and surprising things can happen trying to compile C using a C++ compiler. Rust makes the interface explicit, which is easier to reason about.
- ridiculous_fish 8y agoI'm not super-familiar with Rust's C interop - it it really that good? Does it support preprocessor macros? Can it inline C functions from header files? Does it know about function attributes like pure? If you believe that C++ "sacrificed" for backwards compatibility (and I agree), well what was that sacrifice for anyways, if not better compatibility?
- ilovecaching 8y agoIt is easy in the sense that Rust can match the ABI and calling convention of C with a single annotation or keyword. No, Rust can't use C macros, because it's calling through an ABI that is connected by the linker. The preprocessor has long since run. This is also why pure and inlining are separate issues. It is a much better interop story to use this type of FFI. As I've previously said, C++ compilers are usually not 100% compatible with their C counterparts, and will actually change the semantics of attributes and make different decisions about inlining. It is far better to use a C compiler to get machine code that matches the intended semantics, and call over a well formed ABI that to take the subset language approach. Not to mention that using C libraries from C++ adds a different convention for memory management in the middle of what should be RAII code, which almost always leads to memory leaks. By using the Rust FFI, Rust will at least make sure you are treating unsafe code in a controlled manner.
- pjmlp 8y agoWhile it is nice that Rust offers such FFI, it isn't specific of Rust. Like in any other language with similar feature, it is still a pain to manage in large APIs.
- ridiculous_fish 8y agoSo Rust's C interop is limited to implementing the platform calling conventions? It's nice that Rust can do that but this is NOT better, it's a significant limitation. A deliberate, defensible one, but a limitation none-the-less. Here's a real example. If you write C, you'll probably make a system call, and then check errno. You might also write to errno, e.g. save and restore. errno is implemented differently on every platform, but a C program can include errno.h, and use it portably. C++ can do the same thing: include errno.h and you're done. But Rust can't read the C header, so it must literally special-case every OS [1]. errno is just one thing, but there's a long tail: different platforms have different types and size and function names and signatures, especially the ancient system-y stuff. "Rust is better than C++ at C interop" is an absurd take. The point of Rust is to displace this stuff, not be the best at integrating with it. 1: https://github.com/rust-lang/rust/blob/7cb3ee453b829a513749eb49e6cbe7fe4da527b1/src/libstd/sys/unix/os.rs#L28 https://github.com/rust-lang/rust/blob/7cb3ee453b829a513749e...
- nicoburns 8y ago> errno is implemented differently on every platform, > But Rust can't read the C header, so it must literally special-case every OS [1]. That's a bit of an odd point. You're saying that the C standard library implementation of errno is different on each platform, but abstracted in the standard library so that C programs can just import it and run a portable function. ...and then you complain that Rust does the same...
- qznc 8y agoI'd say there are roughly three classes of C compatibility: Tier 1 is C++ and ObjC, where you can use C headers nearly directly. Tier 2 is where you have to create (and maintain) bindings, but you can map practically everything. Here is Rust, D, Nim, Go, etc. More work than tier 1 is necessary but no loss of performance (except maybe inlining and macros). There are distinctions within this class depending on how well macros etc can be mapped, but usually people map to the ABI instead of the API. Tier 3 is where you cannot map directly and inefficient adapters must be made. This is for example Java, which does not have struct or size_t. Also nearly all scripting languages (Python, Ruby, Lua, etc).
- jeffdavis 8y agoC++ interoperating with C makes it very C-like and often removes the benefit of using C++. In rust, you can do dynamic dispatch via trait objects over C structs. In C++, that wouldn't work, because dynamic dispatch uses inheritance and it needs to add a virtual method table pointer in the struct, meaning that you'd need to translate/copy the struct into a C+ one. Also, rust has neat tricks. An Option type of a reference is represented as a single pointer where NULL means None. That means your plain old C struct can be interpeted as an Option type in rust without copying/translation.
- ridiculous_fish 8y agoI think I have understood your examples: 1. In Rust, you can define a method on a trait object (a type that encloses a C struct), and then invoke it dynamically with the syntactic appearance that 'self' is the struct. C++ does not allow you to add virtual methods to C structs. 2. In Rust, given a C struct T, you can convert T* to an Option<&T> without copying. This stuff is all gravy but I wonder about the meat. Is there a good story for consuming C headers directly? C structs are typically a hash of typedefs and preprocessor gunk; can Rust navigate that?
- steveklabnik 8y agoThere’s a tool, bindgen, that can read in C headers (and limited C++ support, I believe) and produce the bindings Rust needs to understand them. It’s not perfect but IIRC it’s good enough for Firefox.
- kazinator 8y agoRust is magic pixie dust, whereas C++ is limited to manipulating ones and zeros, which severely curtails the available techniques. class cpp_class { c_struct *pimpl; public: cpp_class(c_struct *p) : pimpl(p) { } virtual void whatever(); } class derived_cpp_class : public cpp_class { public: derived_cpp_class(c_struct *p) : cpp_class(p) { } virtual void whatever(); // override };
- 8y ago