• 0 Posts
  • 3 Comments
Joined 2 years ago
cake
Cake day: June 12th, 2023

help-circle
  • It’s because Rust is a significantly higher level language than C (and C++ gets held back by it’s C roots). In C there’s no such thing as a method, there’s only pointers. The closest you get to a method is a function pointer. C++ expanded on that with the concepts of class, object, and method, but stopped half way leaving an object and a pointer to an object as distinctly different concepts that are treated differently by the language. In order to do anything with a pointer besides change its address in C++ it must be dereferenced. The -> operator in C++ is really syntactic sugar for a dereference followed by a method invocation. In other words these are equivalent foo->bar() and (*foo).bar() as stated in the quote you provided. C and C++ treat pointers as their fundamental abstraction and treat everything as special cases of pointers.

    Rust in contrast treats Objects as first class abstractions. It doesn’t really matter whether you’re dealing with the owned object or a reference to that object owned by a different scope, in either case the compiler knows at compile time what its type is and what traits it implements. Given that knowledge whether the method is invoked from the owned instance or a reference it’s treated exactly the same. Further because pointers as opposed to references are treated as second class citizens (relegated to the “here be dragons” of unsafe), the concerns of C/C++ about distinguishing between a pointer assignment and a pointer dereference aren’t particularly important. In general the times you need to explicitly dereference something are far more uncommon in Rust, with the compiler generally being able to work out on its own when it needs to dereference something or not.

    The bit about the receiver just means that the compiler at compile time knows the actual concrete type of all references with the exception of dyn references which force compile time dynamic dispatch (in which case the compiler inserts and utilizes a vtable exactly like C++ does).



  • I’m not sure exactly how to solve your problem, but one thing that occurs to me is that lifetimes and references are really a compile time semantic. If you’re dynamically loading something then you can’t assert lifetimes, at least not safely. So for point 2 I feel like you’d need to create an unsafe layer in between the app and dynamically loaded plugins and then wrap that in a safe API.

    For point 3 I suspect you’d need to look at the macro system. Some kind of like load_plugins!("~/.config/myapp/plugins") macro stuck in an appropriate place in the code that at compile time can check that folder and generate the appropriate glue code to register and use everything. One thing I’m not entirely sure about though is if you’d have permission to access folders outside of the project at compile time, there’s a chance the compiler would refuse to do so, but I don’t know enough about macros or the way they’re sandboxed (or not sandboxed) to say for sure.