3 ms·
C++ has reasonable dynamic linking (there are ABI breaks, but I only remember only one really bad one with std::basic_string and C++11), obviously excluding a l
by cozzyd 10mo ago
C++ has reasonable dynamic linking (there are ABI breaks, but I only remember only one really bad one with std::basic_string and C++11), obviously excluding a lot of metaprogramming features, but a lot of C++ dynamic libraries exist that are widely used. Supposedly Swift does a better job, though I'm not familiar. Yes, Rust can dynamically link with a C ABI (as can any language) but it loses a lot of the expressiveness (I imagine, I'm not a rust developer) to have to use the C ABI.
Dynamic languages of course support dynamic linking.
- ninkendo 10mo ago> there are ABI breaks, but I only remember only one really bad one with std::basic_string and C++11 ABI breaks are everywhere in C++... consider a class class foo { public: foo(); void do_something(); private: int x; } and an impl in the dynamic library: #include "foo.h" foo::foo() { this->x = 0; } void foo::do_something() { std::cout << this->x << std::endl; } You build a libfoo.so and clients use it, calling `foo f; f.do_something();`, it calls your library and it's great. But as soon as you ship a new version that adds a new field to foo (still source-code compatible): class foo { public: foo(); void do_something(); private: int x; int y; }; With a new function body in your shared object: void foo::do_something() { std::cout << this->x << this->y << std::endl; } You're hosed. Clients have to recompile, or they get: $ ./main 0, 0 *** stack smashing detected ***: terminated [1] 2625391 IOT instruction (core dumped) ./main Because the size information for an instance of foo is only known at compile-time, so the clients aren't allocating enough space on the stack for it (ditto the heap if you're using `new foo();`) The way around this is awkward and involves the pimpl pattern and moving all your constructors out-of-line... but you also need to freeze all virtual methods (even just adding a new one breaks ABI), and avoid using any template-heavy std:: types (not even std::string), since those are often fragile. Most people just give up and offer an extern "C" API, because that has the added benefit that it's compatible across compilers. "true" C++ shared libraries are crazy difficult to maintain. It's the reason microsoft invented COM. Swift goes through crazy lengths to make this work, and it's impressive: https://faultlore.com/blah/swift-abi/#resilient-type-layout https://faultlore.com/blah/swift-abi/#resilient-type-layout Rust would have to do something like Swift is doing, and that's probably never going to happen.
- cozzyd 10mo agoSure, you can break ABI in a library, but the compiler doesn't force you to, is what I mean. Same as breaking ABI in C when you change a struct...