rpcsx/rpcs3/util/dyn_lib.hpp

113 lines
2.1 KiB
C++
Raw Normal View History

2020-12-06 17:34:16 +01:00
#pragma once
2020-02-26 16:41:23 +01:00
2016-05-08 09:38:40 +02:00
#include <string>
namespace utils
{
class dynamic_library
{
void* m_handle = nullptr;
2016-05-08 09:38:40 +02:00
public:
dynamic_library() = default;
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;
dynamic_library(dynamic_library&& other)
: m_handle(other.m_handle)
{
other.m_handle = nullptr;
}
dynamic_library& operator=(const dynamic_library&) = delete;
dynamic_library& operator=(dynamic_library&& other)
{
std::swap(m_handle, other.m_handle);
return *this;
}
2016-05-08 09:38:40 +02:00
~dynamic_library();
bool load(const std::string& path);
2016-05-08 09:38:40 +02:00
void close();
private:
void* get_impl(const std::string& name) const;
2016-05-08 09:38:40 +02:00
public:
template <typename Type = void>
Type* get(const std::string& name) const
2016-05-08 09:38:40 +02:00
{
Type* result;
*reinterpret_cast<void**>(&result) = get_impl(name);
2016-05-08 09:38:40 +02:00
return result;
}
template <typename Type>
bool get(Type*& function, const std::string& name) const
2016-05-08 09:38:40 +02:00
{
*reinterpret_cast<void**>(&function) = get_impl(name);
2016-05-08 09:38:40 +02:00
return function != nullptr;
2016-05-08 09:38:40 +02:00
}
bool loaded() const;
explicit operator bool() const;
};
// (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;
const char* const lib;
const char* const name;
// Constant initialization
constexpr dynamic_import(const char* lib, const char* name) noexcept
: ptr(-1)
, lib(lib)
, name(name)
{
}
void init() noexcept
{
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
}
operator bool() noexcept
2018-05-03 00:44:44 +02:00
{
if (ptr == umax) [[unlikely]]
{
init();
}
2018-05-03 00:44:44 +02:00
return ptr != 0;
2018-05-03 00:44:44 +02:00
}
// Caller
R operator()(Args... args) noexcept
2018-05-03 00:44:44 +02:00
{
if (ptr == umax) [[unlikely]]
{
init();
}
return reinterpret_cast<R (*)(Args...)>(ptr.load())(args...);
}
};
2016-05-08 09:38:40 +02:00
}
#define DYNAMIC_IMPORT(lib, name, ...) inline utils::dynamic_import<__VA_ARGS__> name(lib, #name);