Improve DYNAMIC_IMPORT

Don't call get_proc_address every time if if failed.
Also rename Utilities/dynamic_library.h to util/dyn_lib.hpp
This commit is contained in:
Nekotekina 2020-11-10 01:11:30 +03:00
parent cdaa8cb5c4
commit bd5253047b
7 changed files with 27 additions and 23 deletions

View file

@ -1,69 +0,0 @@
#include "stdafx.h"
#include "dynamic_library.h"
#ifdef _WIN32
#include <Windows.h>
#else
#include <dlfcn.h>
#endif
namespace utils
{
dynamic_library::dynamic_library(const std::string& path)
{
load(path);
}
dynamic_library::~dynamic_library()
{
close();
}
bool dynamic_library::load(const std::string& path)
{
#ifdef _WIN32
m_handle = LoadLibraryA(path.c_str());
#else
m_handle = dlopen(path.c_str(), RTLD_LAZY);
#endif
return loaded();
}
void dynamic_library::close()
{
#ifdef _WIN32
FreeLibrary(reinterpret_cast<HMODULE>(m_handle));
#else
dlclose(m_handle);
#endif
m_handle = nullptr;
}
void* dynamic_library::get_impl(const std::string& name) const
{
#ifdef _WIN32
return reinterpret_cast<void*>(GetProcAddress(reinterpret_cast<HMODULE>(m_handle), name.c_str()));
#else
return dlsym(m_handle, name.c_str());
#endif
}
bool dynamic_library::loaded() const
{
return m_handle != nullptr;
}
dynamic_library::operator bool() const
{
return loaded();
}
void* get_proc_address(const char* lib, const char* name)
{
#ifdef _WIN32
return reinterpret_cast<void*>(GetProcAddress(GetModuleHandleA(lib), name));
#else
return dlsym(dlopen(lib, RTLD_NOLOAD), name);
#endif
}
}

View file

@ -1,94 +0,0 @@
#pragma once
#include <string>
namespace utils
{
class dynamic_library
{
void* m_handle = nullptr;
public:
dynamic_library() = default;
dynamic_library(const std::string& path);
~dynamic_library();
bool load(const std::string& path);
void close();
private:
void* get_impl(const std::string& name) const;
public:
template <typename Type = void>
Type* get(const std::string& name) const
{
Type* result;
*reinterpret_cast<void**>(&result) = get_impl(name);
return result;
}
template <typename Type>
bool get(Type*& function, const std::string& name) const
{
*reinterpret_cast<void**>(&function) = get_impl(name);
return function != nullptr;
}
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...)>
{
R (*ptr)(Args...);
const char* const lib;
const char* const name;
// Constant initialization
constexpr dynamic_import(const char* lib, const char* name)
: ptr(nullptr)
, lib(lib)
, name(name)
{
}
void init()
{
if (!ptr)
{
// TODO: atomic
ptr = reinterpret_cast<R (*)(Args...)>(get_proc_address(lib, name));
}
}
operator bool()
{
init();
return ptr;
}
// Caller
R operator()(Args... args)
{
init();
return ptr(args...);
}
};
}
#define DYNAMIC_IMPORT(lib, name, ...) inline utils::dynamic_import<__VA_ARGS__> name(lib, #name);

View file

@ -4,7 +4,7 @@
#include "types.h"
#include "util/atomic.hpp"
#include "dynamic_library.h"
#include "util/dyn_lib.hpp"
#ifdef _WIN32
#define NOMINMAX