From 4cb29fbc2d20f20e9d605796b137b4b70363113a Mon Sep 17 00:00:00 2001 From: 0scar Date: Fri, 28 Jul 2023 16:32:58 +0200 Subject: Implement hotloading * This commit implements dltools.{c,h}: _A simple wrapper around libdl / dlfcn.h_ * Reload states when done initializing engine, if hotloading is enabled. * Adds general function types for state functions. --- src/state.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 59 insertions(+), 7 deletions(-) (limited to 'src/state.c') diff --git a/src/state.c b/src/state.c index 853037f..1d59ad7 100644 --- a/src/state.c +++ b/src/state.c @@ -1,5 +1,6 @@ #include #include +#include typedef StateType state_update_t(void*); @@ -17,18 +18,22 @@ typedef struct name##_state name##_state; \ typedef void (state_##name##_init_t)(name##_state*); \ typedef void (state_##name##_free_t)(name##_state*); \ typedef StateType (state_##name##_update_t)(name##_state*); -#include +#include #undef State #ifdef DAW_BUILD_HOTRELOAD + // When hotreloading is enabled, we want to assign state function pointers // dynamically. -#define State(name) \ -state_##name##_init_t *name##_init = NULL; \ -state_##name##_free_t *name##_free = NULL; \ -state_##name##_update_t *name##_update = NULL; - +#define State(name) \ +state_##name##_init_t *name##_init = NULL; \ +state_##name##_free_t *name##_free = NULL; \ +state_##name##_update_t *name##_update = NULL; \ + \ +void* libstate_##name = NULL; \ +const char* libstate_##name##_str = "lib" #name ".so"; #else + // Otherwise we just declare them. #define State(name) \ state_##name##_init_t name##_init; \ @@ -36,9 +41,11 @@ state_##name##_free_t name##_free; \ state_##name##_update_t name##_update; #endif -#include +#include #undef State +#include + void State_init(StateType type, memory *mem) { switch (type) { #define State(name) \ @@ -80,11 +87,19 @@ void State_free(StateType type, memory *mem) { StateType (*State_updateFunc(StateType type))(void*) { switch (type) { +#ifdef DAW_BUILD_HOTRELOAD +#define State(name) \ + case (STATE_##name): { \ + return (state_update_t*)name##_update; \ + break; \ + } +#else #define State(name) \ case (STATE_##name): { \ return (state_update_t*)&name##_update; \ break; \ } +#endif #include #undef State case STATE_null: @@ -116,3 +131,40 @@ StateType State_update(StateType type, memory *mem) { } return next_state; } + +bool State_reload(StateType type) { +#ifdef DAW_BUILD_HOTRELOAD + switch (type) { +#define State(name) \ + case (STATE_##name): { \ + if (libstate_##name == NULL) { \ + libstate_##name = dynamic_library_open(libstate_##name##_str); \ + } else { \ + libstate_##name = \ + dynamic_library_reload(libstate_##name, libstate_##name##_str); \ + } \ + if (libstate_##name == NULL) { \ + ERROR("Failed loading shared object: %s (%s)", \ + libstate_##name##_str, \ + dynamic_library_get_error()); \ + return false; \ + } \ + \ + name##_init = (state_##name##_init_t*)dynamic_library_get_symbol(libstate_##name, STR( name##_init ) ); \ + name##_free = (state_##name##_free_t*)dynamic_library_get_symbol(libstate_##name, STR( name##_free ) ); \ + name##_update = (state_##name##_update_t*)dynamic_library_get_symbol(libstate_##name, STR( name##_update ) ); \ + break; \ + } +#include +#undef State + case STATE_null: + case STATE_quit: + ERROR("Invalid state"); + DEBUG("Got %s state.\n", StateTypeStr[type]); + break; + default: + exit(EXIT_FAILURE); + } +#endif + return true; +} -- cgit v1.3