86 lines
3.0 KiB
C++
86 lines
3.0 KiB
C++
#pragma once
|
|
#if __has_include(<dlfcn.h>)
|
|
#include <dlfcn.h>
|
|
|
|
#include <cassert>
|
|
|
|
namespace libremidi
|
|
{
|
|
class dylib_loader
|
|
{
|
|
public:
|
|
explicit dylib_loader(const char* const so)
|
|
{
|
|
impl = dlopen(so, RTLD_LAZY | RTLD_LOCAL | RTLD_NODELETE);
|
|
}
|
|
|
|
dylib_loader(const dylib_loader&) noexcept = delete;
|
|
dylib_loader& operator=(const dylib_loader&) noexcept = delete;
|
|
dylib_loader(dylib_loader&& other) noexcept
|
|
{
|
|
impl = other.impl;
|
|
other.impl = nullptr;
|
|
}
|
|
|
|
dylib_loader& operator=(dylib_loader&& other) noexcept
|
|
{
|
|
impl = other.impl;
|
|
other.impl = nullptr;
|
|
return *this;
|
|
}
|
|
|
|
~dylib_loader()
|
|
{
|
|
if (impl)
|
|
{
|
|
dlclose(impl);
|
|
}
|
|
}
|
|
|
|
template <typename T>
|
|
T symbol(const char* const sym) const noexcept
|
|
{
|
|
assert(impl);
|
|
return reinterpret_cast<T>(dlsym(impl, sym));
|
|
}
|
|
|
|
operator bool() const noexcept { return bool(impl); }
|
|
|
|
private:
|
|
void* impl{};
|
|
};
|
|
|
|
}
|
|
|
|
#define LIBREMIDI_SYMBOL_NAME_S(prefix, name) #prefix "_" #name
|
|
#define LIBREMIDI_SYMBOL_NAME(prefix, name) prefix##_##name
|
|
#define LIBREMIDI_SYMBOL_DEF(prefix, name) \
|
|
decltype(&::LIBREMIDI_SYMBOL_NAME(prefix, name)) name{};
|
|
#define LIBREMIDI_SYMBOL_INIT(prefix, name) \
|
|
{ \
|
|
name = library.symbol<decltype(&::LIBREMIDI_SYMBOL_NAME(prefix, name))>( \
|
|
LIBREMIDI_SYMBOL_NAME_S(prefix, name)); \
|
|
if (!name) \
|
|
{ \
|
|
available = false; \
|
|
return; \
|
|
} \
|
|
}
|
|
|
|
// Because some libs have names that are C++ keywords, e.g. udev_new:
|
|
#define LIBREMIDI_SYMBOL_NAME2_S(prefix, name, varname) #prefix "_" #name
|
|
#define LIBREMIDI_SYMBOL_NAME2(prefix, name, varname) prefix##_##name
|
|
#define LIBREMIDI_SYMBOL_DEF2(prefix, name, varname) \
|
|
decltype(&::LIBREMIDI_SYMBOL_NAME2(prefix, name, varname)) varname{};
|
|
#define LIBREMIDI_SYMBOL_INIT2(prefix, name, varname) \
|
|
{ \
|
|
varname = library.symbol<decltype(&::LIBREMIDI_SYMBOL_NAME2(prefix, name, varname))>( \
|
|
LIBREMIDI_SYMBOL_NAME2_S(prefix, name, varname)); \
|
|
if (!varname) \
|
|
{ \
|
|
available = false; \
|
|
return; \
|
|
} \
|
|
}
|
|
#endif
|