Created
September 16, 2018 06:16
-
-
Save hotwatermorning/c19afd09d1e53729796bdc2f004e3165 to your computer and use it in GitHub Desktop.
Module.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#if defined(_MSC_VER) | |
#include <windows.h> | |
#else | |
#include <cstdlib> | |
#include <cwchar> | |
#include <vector> | |
#include <dlfcn.h> | |
#endif | |
struct Module | |
{ | |
#if defined(_MSC_VER) | |
typedef HMODULE platform_module_type; | |
platform_module_type load_impl(const char *path) { return LoadLibraryA(path); } | |
platform_module_type load_impl(const wchar_t *path) { return LoadLibraryW(path); } | |
void unload_impl(platform_module_type handle) { assert(handle); FreeLibrary(handle); } | |
#else | |
typedef void * platform_module_type; | |
platform_module_type load_impl(const char *path) { return dlopen(path, RTLD_LAZY); } | |
platform_module_type load_impl(const wchar_t *path) | |
{ | |
auto const error_result = static_cast<std::size_t>(-1); | |
auto const num_estimated_bytes = std::wcstombs(NULL, path, 0); | |
if (error_result == num_estimated_bytes) { | |
return NULL; | |
} | |
auto const buffer_length = (num_estimated_bytes / sizeof(char)) + 1; | |
std::vector<char> tmp(buffer_length); | |
std::mbstate_t state = std::mbstate_t(); | |
auto const num_converted_bytes = std::wcsrtombs(tmp.data(), | |
&path, | |
buffer_length * sizeof(char), | |
&state); | |
if (error_result == num_converted_bytes) { | |
return NULL; | |
} | |
return load(tmp.data()); | |
} | |
platform_module_type load(const char *path) | |
{ | |
return dlopen(path, RTLD_LAZY); | |
} | |
void unload_impl(platform_module_type handle) { assert(handle); dlclose(handle); } | |
#endif | |
public: | |
typedef platform_module_type module_type; | |
Module() {} | |
explicit | |
Module(char const *path) | |
: module_(load_impl(path)) | |
{} | |
explicit | |
Module(wchar_t const *path) | |
: module_(load_impl(path)) | |
{} | |
Module(module_type module) | |
: module_(module) | |
{} | |
Module(Module &&r) | |
: module_(std::exchange(r.module_, platform_module_type())) | |
{ | |
r.module_ = nullptr; | |
} | |
Module & operator=(Module &&r) | |
{ | |
module_ = std::exchange(r.module_, platform_module_type()); | |
return *this; | |
} | |
void * get_proc_address(char const *function_name) const | |
{ | |
#if defined(_MSC_VER) | |
return GetProcAddress(module_, function_name); | |
#else | |
return dlsym(module_, function_name); | |
#endif | |
} | |
~Module() | |
{ | |
if(module_) { unload_impl(module_); } | |
} | |
public: | |
module_type get() { return module_; } | |
module_type get() const { return module_; } | |
module_type release() { return std::exchange(module_, platform_module_type()); } | |
template<class... Args> | |
void reset(Args&&... args) { *this = Module(args...); } | |
explicit | |
operator bool() const { return module_ != platform_module_type(); } | |
private: | |
module_type module_ = platform_module_type(); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment