2020-02-26 15:41:23 +00:00
|
|
|
|
#pragma once
|
|
|
|
|
|
2016-05-08 07:38:40 +00:00
|
|
|
|
#include <string>
|
|
|
|
|
|
|
|
|
|
namespace utils
|
|
|
|
|
{
|
|
|
|
|
class dynamic_library
|
|
|
|
|
{
|
2019-11-28 18:18:37 +00:00
|
|
|
|
void* m_handle = nullptr;
|
2016-05-08 07:38:40 +00:00
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
dynamic_library() = default;
|
2019-11-28 18:18:37 +00:00
|
|
|
|
dynamic_library(const std::string& path);
|
2016-05-08 07:38:40 +00:00
|
|
|
|
|
|
|
|
|
~dynamic_library();
|
|
|
|
|
|
2019-11-28 18:18:37 +00:00
|
|
|
|
bool load(const std::string& path);
|
2016-05-08 07:38:40 +00:00
|
|
|
|
void close();
|
|
|
|
|
|
|
|
|
|
private:
|
2019-11-28 18:18:37 +00:00
|
|
|
|
void* get_impl(const std::string& name) const;
|
2016-05-08 07:38:40 +00:00
|
|
|
|
|
|
|
|
|
public:
|
2019-11-28 18:18:37 +00:00
|
|
|
|
template <typename Type = void>
|
|
|
|
|
Type* get(const std::string& name) const
|
2016-05-08 07:38:40 +00:00
|
|
|
|
{
|
2019-11-28 18:18:37 +00:00
|
|
|
|
Type* result;
|
|
|
|
|
*reinterpret_cast<void**>(&result) = get_impl(name);
|
2016-05-08 07:38:40 +00:00
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-28 18:18:37 +00:00
|
|
|
|
template <typename Type>
|
|
|
|
|
bool get(Type*& function, const std::string& name) const
|
2016-05-08 07:38:40 +00:00
|
|
|
|
{
|
2019-11-28 18:18:37 +00:00
|
|
|
|
*reinterpret_cast<void**>(&function) = get_impl(name);
|
2016-05-08 07:38:40 +00:00
|
|
|
|
|
2019-11-28 18:18:37 +00:00
|
|
|
|
return function != nullptr;
|
2016-05-08 07:38:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool loaded() const;
|
|
|
|
|
explicit operator bool() const;
|
|
|
|
|
};
|
2017-01-24 13:52:15 +00: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...)>
|
|
|
|
|
{
|
2019-11-28 18:18:37 +00:00
|
|
|
|
R (*ptr)(Args...);
|
2017-01-24 13:52:15 +00:00
|
|
|
|
const char* const lib;
|
|
|
|
|
const char* const name;
|
|
|
|
|
|
|
|
|
|
// Constant initialization
|
|
|
|
|
constexpr dynamic_import(const char* lib, const char* name)
|
2019-11-28 18:18:37 +00:00
|
|
|
|
: ptr(nullptr)
|
|
|
|
|
, lib(lib)
|
|
|
|
|
, name(name)
|
2017-01-24 13:52:15 +00:00
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-02 22:44:44 +00:00
|
|
|
|
void init()
|
2017-01-24 13:52:15 +00:00
|
|
|
|
{
|
|
|
|
|
if (!ptr)
|
|
|
|
|
{
|
|
|
|
|
// TODO: atomic
|
2019-11-28 18:18:37 +00:00
|
|
|
|
ptr = reinterpret_cast<R (*)(Args...)>(get_proc_address(lib, name));
|
2017-01-24 13:52:15 +00:00
|
|
|
|
}
|
2018-05-02 22:44:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
operator bool()
|
|
|
|
|
{
|
|
|
|
|
init();
|
|
|
|
|
|
|
|
|
|
return ptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Caller
|
|
|
|
|
R operator()(Args... args)
|
|
|
|
|
{
|
|
|
|
|
init();
|
2017-01-24 13:52:15 +00:00
|
|
|
|
|
|
|
|
|
return ptr(args...);
|
|
|
|
|
}
|
|
|
|
|
};
|
2016-05-08 07:38:40 +00:00
|
|
|
|
}
|
2017-01-24 13:52:15 +00:00
|
|
|
|
|
2018-10-13 20:58:02 +00:00
|
|
|
|
#define DYNAMIC_IMPORT(lib, name, ...) inline utils::dynamic_import<__VA_ARGS__> name(lib, #name);
|