Files
viseq/include/libremidi/backends/linux/dylib_loader.hpp
T

86 lines
3.0 KiB
C++
Raw Normal View History

2024-10-09 02:01:23 +02:00
#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