Getting a trait object from a shared library

Hello everybody!

I wonder, is it possible for a Rust shared library with C interface to reliably expose trait objects? For example, using a double-boxing method, in which a extern "C" shared library function first allocates something like Box<Box<dyn AbstractFactory>>, which is then leak()ed and turned into a pointer (on C side, it can look like void* or incomplete-type pointer), after which, the "receiving" Rust code uses Box::from_raw() to restore the original value. To remove the double-boxing, the AbstractFactory trait can have a method like fn virtual_clone(&self) -> Result<Box<dyn AbstractFactory>,CloneError>. Then, the application code can create objects from the shared library using the abstract factory (which would also be exposed as trait objects).

The problem I'm worried about, would the "receiving" side perceive the vtables exactly as the shared library created them? Can there be a problem in which, the shared library has placed a vtable for a trait object with one layout, but the app side read it expecting a different layout?

My understanding is that the vtable layout (and all other formats and layouts except those defined by repr(C)) can change from release to release, including minor and bugfix releases.So the library and its Rust clients must be compiled with exactly the same Rust release.

1 Like

Not only that, the crate containing the trait that's exposed needs to be compiled in the same way (e.g. same build flags and same transitive dependencies versions) in both the shared library and the "receiving" side.

2 Likes

For now, I would recommend one of these two crates for doing shared library ABI things if both sides of the boundary are written in Rust:

Rather than trying to invent your own solution, other people have already solved it.

1 Like