diff options
-rw-r--r-- | meson.build | 1 | ||||
-rw-r--r-- | src/dylib.c | 67 | ||||
-rw-r--r-- | src/dylib.h | 35 | ||||
-rw-r--r-- | src/lib.c | 21 | ||||
-rw-r--r-- | src/lilv_internal.h | 24 | ||||
-rw-r--r-- | src/plugin.c | 11 | ||||
-rw-r--r-- | src/world.c | 25 |
7 files changed, 131 insertions, 53 deletions
diff --git a/meson.build b/meson.build index 92a0645..4c1cd99 100644 --- a/meson.build +++ b/meson.build @@ -237,6 +237,7 @@ cpp_headers = files('include/lilv/lilvmm.hpp') sources = files( 'src/collections.c', + 'src/dylib.c', 'src/instance.c', 'src/lib.c', 'src/node.c', diff --git a/src/dylib.c b/src/dylib.c new file mode 100644 index 0000000..4c6c219 --- /dev/null +++ b/src/dylib.c @@ -0,0 +1,67 @@ +// Copyright 2020-2024 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC + +#include "dylib.h" + +#ifdef _WIN32 + +# include <windows.h> + +void* +dylib_open(const char* const filename, const unsigned flags) +{ + (void)flags; + return LoadLibrary(filename); +} + +int +dylib_close(DylibLib* const handle) +{ + return !FreeLibrary((HMODULE)handle); +} + +const char* +dylib_error(void) +{ + return "Unknown error"; +} + +DylibFunc +dylib_func(DylibLib* handle, const char* symbol) +{ + return (DylibFunc)GetProcAddress((HMODULE)handle, symbol); +} + +#else + +# include <dlfcn.h> + +void* +dylib_open(const char* const filename, const unsigned flags) +{ + return dlopen(filename, flags == DYLIB_LAZY ? RTLD_LAZY : RTLD_NOW); +} + +int +dylib_close(DylibLib* const handle) +{ + return dlclose(handle); +} + +const char* +dylib_error(void) +{ + return dlerror(); +} + +DylibFunc +dylib_func(DylibLib* handle, const char* symbol) +{ + typedef DylibFunc (*VoidFuncGetter)(void*, const char*); + + VoidFuncGetter dlfunc = (VoidFuncGetter)dlsym; + + return dlfunc(handle, symbol); +} + +#endif diff --git a/src/dylib.h b/src/dylib.h new file mode 100644 index 0000000..f2faade --- /dev/null +++ b/src/dylib.h @@ -0,0 +1,35 @@ +// Copyright 2020-2024 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC + +#ifndef LILV_DYLIB_H +#define LILV_DYLIB_H + +/// Flags for dylib_open() +enum DylibFlags { + DYLIB_LAZY = 1U << 0U, ///< Resolve symbols only when referenced + DYLIB_NOW = 1U << 1U, ///< Resolve all symbols on library load +}; + +/// An opaque dynamically loaded shared library +typedef void DylibLib; + +/// A function from a shared library +typedef void (*DylibFunc)(void); + +/// Open a shared library +DylibLib* +dylib_open(const char* filename, unsigned flags); + +/// Close a shared library opened with dylib_open() +int +dylib_close(DylibLib* handle); + +/// Return a human-readable description of any error since the last call +const char* +dylib_error(void); + +/// Return a pointer to a function in a shared library, or null +DylibFunc +dylib_func(DylibLib* handle, const char* symbol); + +#endif // LILV_DYLIB_H @@ -1,6 +1,7 @@ // Copyright 2012-2019 David Robillard <d@drobilla.net> // SPDX-License-Identifier: ISC +#include "dylib.h" #include "lilv_internal.h" #include <lilv/lilv.h> @@ -8,10 +9,6 @@ #include <serd/serd.h> #include <zix/tree.h> -#ifndef _WIN32 -# include <dlfcn.h> -#endif - #include <stdint.h> #include <stdlib.h> @@ -37,33 +34,33 @@ lilv_lib_open(LilvWorld* world, return NULL; } - dlerror(); - void* lib = dlopen(lib_path, RTLD_NOW); + dylib_error(); + void* lib = dylib_open(lib_path, DYLIB_NOW); if (!lib) { - LILV_ERRORF("Failed to open library %s (%s)\n", lib_path, dlerror()); + LILV_ERRORF("Failed to open library %s (%s)\n", lib_path, dylib_error()); serd_free(lib_path); return NULL; } LV2_Descriptor_Function df = - (LV2_Descriptor_Function)lilv_dlfunc(lib, "lv2_descriptor"); + (LV2_Descriptor_Function)dylib_func(lib, "lv2_descriptor"); LV2_Lib_Descriptor_Function ldf = - (LV2_Lib_Descriptor_Function)lilv_dlfunc(lib, "lv2_lib_descriptor"); + (LV2_Lib_Descriptor_Function)dylib_func(lib, "lv2_lib_descriptor"); const LV2_Lib_Descriptor* desc = NULL; if (ldf) { desc = ldf(bundle_path, features); if (!desc) { LILV_ERRORF("Call to %s:lv2_lib_descriptor failed\n", lib_path); - dlclose(lib); + dylib_close(lib); serd_free(lib_path); return NULL; } } else if (!df) { LILV_ERRORF("No `lv2_descriptor' or `lv2_lib_descriptor' in %s\n", lib_path); - dlclose(lib); + dylib_close(lib); serd_free(lib_path); return NULL; } @@ -100,7 +97,7 @@ void lilv_lib_close(LilvLib* lib) { if (--lib->refs == 0) { - dlclose(lib->lib); + dylib_close(lib->lib); ZixTreeIter* i = NULL; if (lib->world->libs && !zix_tree_find(lib->world->libs, lib, &i)) { diff --git a/src/lilv_internal.h b/src/lilv_internal.h index 3693f8a..6dc47ee 100644 --- a/src/lilv_internal.h +++ b/src/lilv_internal.h @@ -23,20 +23,11 @@ extern "C" { #ifdef _WIN32 # include <direct.h> # include <windows.h> -# define dlopen(path, flags) LoadLibrary(path) -# define dlclose(lib) FreeLibrary((HMODULE)lib) # ifdef _MSC_VER # ifndef snprintf # define snprintf _snprintf # endif # endif -static inline const char* -dlerror(void) -{ - return "Unknown error"; -} -#else -# include <dlfcn.h> #endif #ifdef LILV_DYN_MANIFEST @@ -399,21 +390,6 @@ lilv_find_free_path(const char* in_path, bool (*exists)(const char*, const void*), const void* user_data); -typedef void (*LilvVoidFunc)(void); - -/** dlsym wrapper to return a function pointer (without annoying warning) */ -static inline LilvVoidFunc -lilv_dlfunc(void* handle, const char* symbol) -{ -#ifdef _WIN32 - return (LilvVoidFunc)GetProcAddress((HMODULE)handle, symbol); -#else - typedef LilvVoidFunc (*VoidFuncGetter)(void*, const char*); - VoidFuncGetter dlfunc = (VoidFuncGetter)dlsym; - return dlfunc(handle, symbol); -#endif -} - #ifdef LILV_DYN_MANIFEST static const LV2_Feature* const dman_features = {NULL}; diff --git a/src/plugin.c b/src/plugin.c index abb6b31..d828f6f 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -3,6 +3,11 @@ #include "lilv_internal.h" +#ifdef LILV_DYN_MANIFEST +# include "dylib.h" +# include <lv2/dynmanifest/dynmanifest.h> +#endif + #include <lilv/lilv.h> #include <lv2/core/lv2.h> #include <lv2/ui/ui.h> @@ -10,10 +15,6 @@ #include <sord/sord.h> #include <zix/tree.h> -#ifdef LILV_DYN_MANIFEST -# include <lv2/dynmanifest/dynmanifest.h> -#endif - #include <math.h> #include <stdarg.h> #include <stdbool.h> @@ -212,7 +213,7 @@ lilv_plugin_load(LilvPlugin* plugin) if (plugin->dynmanifest) { typedef int (*GetDataFunc)( LV2_Dyn_Manifest_Handle handle, FILE* fp, const char* uri); - GetDataFunc get_data_func = (GetDataFunc)lilv_dlfunc( + GetDataFunc get_data_func = (GetDataFunc)dylib_func( plugin->dynmanifest->lib, "lv2_dyn_manifest_get_data"); if (get_data_func) { const SordNode* bundle = plugin->dynmanifest->bundle->node; diff --git a/src/world.c b/src/world.c index a614918..c23a34e 100644 --- a/src/world.c +++ b/src/world.c @@ -4,6 +4,11 @@ #include "lilv_config.h" #include "lilv_internal.h" +#ifdef LILV_DYN_MANIFEST +# include "dylib.h" +# include <lv2/dynmanifest/dynmanifest.h> +#endif + #include <lilv/lilv.h> #include <lv2/core/lv2.h> #include <lv2/presets/presets.h> @@ -13,10 +18,6 @@ #include <zix/filesystem.h> #include <zix/tree.h> -#ifdef LILV_DYN_MANIFEST -# include <lv2/dynmanifest/dynmanifest.h> -#endif - #include <assert.h> #include <stdbool.h> #include <stdint.h> @@ -551,8 +552,8 @@ lilv_world_load_dyn_manifest(LilvWorld* world, } // Open library - dlerror(); - void* lib = dlopen(lib_path, RTLD_LAZY); + dylib_error(); + void* lib = dylib_open(lib_path, DYLIB_LAZY); if (!lib) { LILV_ERRORF( "Failed to open dynmanifest library `%s' (%s)\n", lib_path, dlerror()); @@ -564,11 +565,11 @@ lilv_world_load_dyn_manifest(LilvWorld* world, // Open dynamic manifest typedef int (*OpenFunc)(LV2_Dyn_Manifest_Handle*, const LV2_Feature* const*); - OpenFunc dmopen = (OpenFunc)lilv_dlfunc(lib, "lv2_dyn_manifest_open"); + OpenFunc dmopen = (OpenFunc)dylib_func(lib, "lv2_dyn_manifest_open"); if (!dmopen || dmopen(&handle, &dman_features)) { LILV_ERRORF("No `lv2_dyn_manifest_open' in `%s'\n", lib_path); sord_iter_free(binaries); - dlclose(lib); + dylib_close(lib); lilv_free(lib_path); continue; } @@ -576,11 +577,11 @@ lilv_world_load_dyn_manifest(LilvWorld* world, // Get subjects (the data that would be in manifest.ttl) typedef int (*GetSubjectsFunc)(LV2_Dyn_Manifest_Handle, FILE*); GetSubjectsFunc get_subjects_func = - (GetSubjectsFunc)lilv_dlfunc(lib, "lv2_dyn_manifest_get_subjects"); + (GetSubjectsFunc)dylib_func(lib, "lv2_dyn_manifest_get_subjects"); if (!get_subjects_func) { LILV_ERRORF("No `lv2_dyn_manifest_get_subjects' in `%s'\n", lib_path); sord_iter_free(binaries); - dlclose(lib); + dylib_close(lib); lilv_free(lib_path); continue; } @@ -647,12 +648,12 @@ lilv_dynmanifest_free(LilvDynManifest* dynmanifest) { typedef int (*CloseFunc)(LV2_Dyn_Manifest_Handle); CloseFunc close_func = - (CloseFunc)lilv_dlfunc(dynmanifest->lib, "lv2_dyn_manifest_close"); + (CloseFunc)dylib_func(dynmanifest->lib, "lv2_dyn_manifest_close"); if (close_func) { close_func(dynmanifest->handle); } - dlclose(dynmanifest->lib); + dylib_close(dynmanifest->lib); lilv_node_free(dynmanifest->bundle); free(dynmanifest); } |