I'm trying to solve one problem is more than two weeks, but no results I have a microkernel system, which is extended by dynamic libraries (dll files under windows). Every time, new library is loaded, core code calls special init function from it. One of plugins creates a GUI (I use piston library for drawing) for this system. During init() call, core code passes configuration parameters, like user window width, height and so on... So, the window may be created within init() function only. Later, core code calls another function of plugin, which is called idle(). idle() uses created window for drawing, so it should use some internal window handler, canvas object , etc.
So, my question is how to create and store all drawing related stuff like piston window, canvas, texture and so on in a struct between different functions calls? Is it possible to use some kind of reference to singleton struct instance within a dll?
If you want to avoid static mut a common solution is to pass some sort of opaque "user data" pointer to each event handler that is created by init().
struct State { ... }
#[no_mangle]
pub extern "C" fn init() -> *mut c_void {
let state = Box::new(State { ... });
Box::into_raw(state).cast()
}
#[no_mangle]
pub extern "C" fn idle(user_data: *mut c_void) {
let state = &mut *(user_data as *mut State);
...
}
Otherwise if the function signatures don't allow passing around extra state like this, your only option will be static variables. That's one of the reasons you see so many static variables in embedded code - hardware interrupts just switch execution to some arbitrary function so there is nowhere to put extra state apart from static variables.
Your kernel should expect plugins to have some sort of unload() function which does cleanup when unloading the plugin (i.e. by calling drop(Box::from_raw(ptr))).
FWIW, the method using static variables also has the same issue where we never clean up things created during init(). It's just that we've been trained to see a pointer and ask who is responsible for freeing it while you don't really think about cleaning up your statics with dynamically loaded modules.