diff options
Diffstat (limited to 'src/disp.c')
-rw-r--r-- | src/disp.c | 81 |
1 files changed, 47 insertions, 34 deletions
@@ -25,17 +25,30 @@ #include "disp.h" -#define dlsym_and_check(dest, name) \ - dest->name = dlsym(dest->dl_handle, #name); \ - if ((!dest->name) || (dest->name == dest->dl_handle)) { \ - char *msg = dlerror(); \ - fprintf(stderr, "calculer: %s\n", msg); \ - dlclose(dest->dl_handle); \ - free(dest); \ - return -1; \ +static void * +load_generic_symbol(struct disp *disp, char *base_name) +{ + char full_name[64] = {0}; + void *ptr; + + strcpy(full_name, disp->name); + strcat(full_name, "_"); + strcat(full_name, base_name); + + ptr = dlsym(disp->dl_handle, full_name); + + if (!ptr) + { + fprintf(stderr, "calculer: %s\n", dlerror()); + destroy_disp(disp); + exit(1); } -static int + return ptr; +} + + +static void load_symbols(struct disp *disp) { void *handle = dlopen(disp->so_path, RTLD_LAZY); @@ -43,24 +56,21 @@ load_symbols(struct disp *disp) if (!handle) { fprintf(stderr, "calculer: %s\n", dlerror()); + destroy_disp(disp); exit(1); } -#ifndef NDEBUG - printf("INFO: successfully loaded symbols from \"%s\"\n", disp->so_path); -#endif + disp->dl_handle = handle; + disp->init = load_generic_symbol(disp, "init"); + disp->display_calc = load_generic_symbol(disp, "display_calc"); + disp->read_input = load_generic_symbol(disp, "read_input"); + disp->display_res = load_generic_symbol(disp, "display_res"); + disp->destroy = load_generic_symbol(disp, "destroy"); + disp->pre_reload = load_generic_symbol(disp, "pre_reload"); + disp->post_reload = load_generic_symbol(disp, "post_reload"); - disp->dl_handle = handle; - dlsym_and_check(disp, init); - dlsym_and_check(disp, display_calc); - dlsym_and_check(disp, read_input); - dlsym_and_check(disp, display_res); - dlsym_and_check(disp, destroy); -#ifndef NDEBUG - dlsym_and_check(disp, pre_reload); - dlsym_and_check(disp, post_reload); -#endif - return 0; + printf("INFO: successfully loaded symbols from \"%s\"\n", + disp->so_path); } struct disp * @@ -74,8 +84,11 @@ get_disp(char *disp_name) strcat(so_path, ".so.0.0.0"); struct disp *disp = malloc(sizeof(*disp)); disp->so_path = strdup(so_path); + disp->name = disp_name; + + load_symbols(disp); - return load_symbols(disp) == 0 ? disp : NULL; + return disp; #else # error "not available yet" #endif @@ -85,8 +98,12 @@ get_disp(char *disp_name) void destroy_disp(struct disp *disp) { - disp->destroy(); - dlclose(disp->dl_handle); + if (disp->destroy) + disp->destroy(); + + if (disp->dl_handle) + dlclose(disp->dl_handle); + free(disp->so_path); free(disp); } @@ -95,22 +112,18 @@ destroy_disp(struct disp *disp) void disp_reload(struct disp *disp) { - int status; printf("INFO: saving state\n"); void *state = disp->pre_reload(); + printf("INFO: closing shared library\n"); dlclose(disp->dl_handle); - printf("INFO: reloading symbols\n"); - status = load_symbols(disp); - if (status == -1) - { - printf("calculer: %s\n", dlerror()); - exit(1); - } + printf("INFO: reloading symbols\n"); + load_symbols(disp); printf("INFO: loading state\n"); disp->post_reload(state); + printf("INFO: reloading done\n"); } #endif |