2020-12-06 17:34:16 +01:00
|
|
|
#pragma once
|
2020-02-26 16:41:23 +01:00
|
|
|
|
2025-04-05 21:50:45 +02:00
|
|
|
#include "util/atomic.hpp"
|
|
|
|
|
#include "util/types.hpp"
|
2016-05-08 09:38:40 +02:00
|
|
|
#include <string>
|
|
|
|
|
|
|
|
|
|
namespace utils
|
|
|
|
|
{
|
|
|
|
|
class dynamic_library
|
|
|
|
|
{
|
2019-11-28 19:18:37 +01:00
|
|
|
void* m_handle = nullptr;
|
2016-05-08 09:38:40 +02:00
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
dynamic_library() = default;
|
2019-11-28 19:18:37 +01:00
|
|
|
dynamic_library(const std::string& path);
|
2016-05-08 09:38:40 +02:00
|
|
|
|
2021-03-30 17:31:46 +02:00
|
|
|
dynamic_library(const dynamic_library&) = delete;
|
|
|
|
|
|
2023-07-19 11:01:44 +02:00
|
|
|
dynamic_library(dynamic_library&& other) noexcept
|
2021-03-30 17:31:46 +02:00
|
|
|
: m_handle(other.m_handle)
|
|
|
|
|
{
|
|
|
|
|
other.m_handle = nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dynamic_library& operator=(const dynamic_library&) = delete;
|
|
|
|
|
|
2023-07-19 11:01:44 +02:00
|
|
|
dynamic_library& operator=(dynamic_library&& other) noexcept
|
2021-03-30 17:31:46 +02:00
|
|
|
{
|
|
|
|
|
std::swap(m_handle, other.m_handle);
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-08 09:38:40 +02:00
|
|
|
~dynamic_library();
|
|
|
|
|
|
2019-11-28 19:18:37 +01:00
|
|
|
bool load(const std::string& path);
|
2025-02-23 14:39:39 +01:00
|
|
|
#ifdef _WIN32
|
|
|
|
|
bool load(const std::wstring& path);
|
|
|
|
|
#endif
|
2016-05-08 09:38:40 +02:00
|
|
|
void close();
|
|
|
|
|
|
|
|
|
|
private:
|
2025-02-23 14:39:39 +01:00
|
|
|
void* get_impl(const char* name) const;
|
2016-05-08 09:38:40 +02:00
|
|
|
|
|
|
|
|
public:
|
2019-11-28 19:18:37 +01:00
|
|
|
template <typename Type = void>
|
2025-02-23 14:39:39 +01:00
|
|
|
Type get(const char* name) const
|
2016-05-08 09:38:40 +02:00
|
|
|
{
|
2025-02-23 14:39:39 +01:00
|
|
|
return reinterpret_cast<Type>(get_impl(name));
|
2016-05-08 09:38:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool loaded() const;
|
|
|
|
|
explicit operator bool() const;
|
|
|
|
|
};
|
2017-01-24 14:52:15 +01:00
|
|
|
|
|
|
|
|
// (assume the lib is always loaded)
|
|
|
|
|
void* get_proc_address(const char* lib, const char* name);
|
|
|
|
|
|
|
|
|
|
template <typename F>
|
|
|
|
|
struct dynamic_import
|
|
|
|
|
{
|
|
|
|
|
static_assert(sizeof(F) == 0, "Invalid function type");
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template <typename R, typename... Args>
|
|
|
|
|
struct dynamic_import<R(Args...)>
|
|
|
|
|
{
|
2020-12-12 14:29:55 +01:00
|
|
|
atomic_t<uptr> ptr;
|
2017-01-24 14:52:15 +01:00
|
|
|
const char* const lib;
|
|
|
|
|
const char* const name;
|
|
|
|
|
|
|
|
|
|
// Constant initialization
|
2020-11-09 23:11:30 +01:00
|
|
|
constexpr dynamic_import(const char* lib, const char* name) noexcept
|
2025-04-05 21:50:45 +02:00
|
|
|
: ptr(-1), lib(lib), name(name)
|
2017-01-24 14:52:15 +01:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-09 23:11:30 +01:00
|
|
|
void init() noexcept
|
2017-01-24 14:52:15 +01:00
|
|
|
{
|
2020-12-12 14:29:55 +01:00
|
|
|
ptr.release(reinterpret_cast<uptr>(get_proc_address(lib, name)));
|
2018-05-03 00:44:44 +02:00
|
|
|
}
|
|
|
|
|
|
2020-11-09 23:11:30 +01:00
|
|
|
operator bool() noexcept
|
2018-05-03 00:44:44 +02:00
|
|
|
{
|
2020-11-09 23:11:30 +01:00
|
|
|
if (ptr == umax) [[unlikely]]
|
|
|
|
|
{
|
|
|
|
|
init();
|
|
|
|
|
}
|
2018-05-03 00:44:44 +02:00
|
|
|
|
2020-11-09 23:11:30 +01:00
|
|
|
return ptr != 0;
|
2018-05-03 00:44:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Caller
|
2020-11-09 23:11:30 +01:00
|
|
|
R operator()(Args... args) noexcept
|
2018-05-03 00:44:44 +02:00
|
|
|
{
|
2020-11-09 23:11:30 +01:00
|
|
|
if (ptr == umax) [[unlikely]]
|
|
|
|
|
{
|
|
|
|
|
init();
|
|
|
|
|
}
|
2017-01-24 14:52:15 +01:00
|
|
|
|
2020-11-09 23:11:30 +01:00
|
|
|
return reinterpret_cast<R (*)(Args...)>(ptr.load())(args...);
|
2017-01-24 14:52:15 +01:00
|
|
|
}
|
|
|
|
|
};
|
2025-04-05 21:50:45 +02:00
|
|
|
} // namespace utils
|
2017-01-24 14:52:15 +01:00
|
|
|
|
2022-06-10 13:27:02 +02:00
|
|
|
#define DYNAMIC_IMPORT(lib, name, ...) inline constinit utils::dynamic_import<__VA_ARGS__> name(lib, #name);
|
2023-05-24 13:58:19 +02:00
|
|
|
#define DYNAMIC_IMPORT_RENAME(lib, declare_name, lib_func_name, ...) inline constinit utils::dynamic_import<__VA_ARGS__> declare_name(lib, lib_func_name);
|