According to your own article (I believe), ABI for dyn Trait objects is unstable, therefore the following use in this guide might be UB:
#[macro_export]
macro_rules! declare_plugin {
($plugin_type:ty, $constructor:path) => {
#[no_mangle]
pub extern "C" fn _plugin_create() -> *mut $crate::Plugin {
// make sure the constructor is the correct type.
let constructor: fn() -> $plugin_type = $constructor;
let object = constructor();
let boxed: Box<$crate::Plugin> = Box::new(object);
Box::into_raw(boxed)
}
};
}
Note the use of *mut $crate::Plugin as the return type. In Rust 2018/2021, it should be *mut dyn $crate::Plugin because Plugin is a trait (instead of a type). And if the layout of trait objects were to change for building the plugin and the host program (though I doubt if this would ever happen), this would result in UB.
For solutions, it seems that abi_stable::sabi_trait could be a candidate, but it looks ad-hoc and pulls in a non-trivial amount of dependencies. Another way would be to just use the "manual vtable" approach mentioned in your blog, which requires some boilerplate, but looks good otherwise.
According to your own article (I believe), ABI for
dyn Trait
objects is unstable, therefore the following use in this guide might be UB:Note the use of
*mut $crate::Plugin
as the return type. In Rust 2018/2021, it should be*mut dyn $crate::Plugin
becausePlugin
is a trait (instead of a type). And if the layout of trait objects were to change for building the plugin and the host program (though I doubt if this would ever happen), this would result in UB.For solutions, it seems that
abi_stable::sabi_trait
could be a candidate, but it looks ad-hoc and pulls in a non-trivial amount of dependencies. Another way would be to just use the "manual vtable" approach mentioned in your blog, which requires some boilerplate, but looks good otherwise.