summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--meson.build1
-rw-r--r--src/dylib.c67
-rw-r--r--src/dylib.h35
-rw-r--r--src/lib.c21
-rw-r--r--src/lilv_internal.h24
-rw-r--r--src/plugin.c11
-rw-r--r--src/world.c25
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
diff --git a/src/lib.c b/src/lib.c
index fcb6f6d..ac676bd 100644
--- a/src/lib.c
+++ b/src/lib.c
@@ -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);
}