I have a library "business logic" crate I want to be able to write multiple binary crate "frontends" or "platform layers" for. These platform layers tend to use libraries calling platform APIs and that tends to imply long compile times. I want to be able to iterate on the business logic crate without needing to recompile the platform layer. But, I want to be able to compile the project into a single binary for each platform, and I'd rather not mess with shared object files/DLLs if I don't have to.
I have a way to do this using a fn
pointer and static mut
, but there's this rust-lang/rust
issue about potentially removing it, so I'd like to know if there is a way to get the results I want without using it.
For reference, the way I got it working was like this:
use platform_types::{Input, Output};
fn update_and_render(input: Input) -> Output {
static mut STATE: logic::State = logic::new();
let state: &mut logic::State = unsafe { &mut STATE };
logic::update_and_render(state, input)
}
fn main() {
platform_layer::run(update_and_render);
}
where the above code is in the main crate, logic
is the business logic crate, platform_layer
is the platform layer crate, and platform_types
contains the common types between the three other crates.
I tried using a RefCell
with try_borrow_mut
I got the error std::cell::RefCell<State> cannot be shared between threads safely
and mentions that Sync
is not implemented for std::cell::RefCell<State>
and the error did not go away if I tried implementing Sync for State
experimentally. I then tried a Mutex
, but as far as I can tell I can't put one in a static
.
EDIT: If it makes a difference, I don't actually expect to need to call the function pointer from multiple threads, although I understand that handing one out implicitly allows that. If I ever (accidentally?) do call the function pointer from multiple threads, a failed debug_assert!
or similar is obviously preferable to UB.