Last active
December 30, 2015 09:08
-
-
Save TheBurnDoc/7806867 to your computer and use it in GitHub Desktop.
This gist demonstrates how to wrap the dynamic loading of DLLs/SOs using some C++11 techniques, including variadic templates and std::function. To load the library you just call lib.load() and then lib.callFunction<return_type>("FuncName", param1, param2 ...).
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
#include <cstdio> | |
#include <string> | |
#include <sstream> | |
#include <stdexcept> | |
#ifdef _MSC_VER | |
#include <Windows.h> | |
#include <direct.h> | |
#else | |
#include <dlfcn.h> | |
#include <unistd.h> | |
#endif | |
#include "DynamicLibrary.h" | |
DynamicLibrary::DynamicLibrary(const std::string& name) : _name(name) | |
{ | |
std::stringstream ss; | |
char cwd[FILENAME_MAX]; | |
#ifdef _MSC_VER | |
_getcwd(cwd, sizeof(cwd)); | |
ss << cwd << "\\" << name << ".dll"; | |
#else | |
getcwd(cwd, sizeof(cwd)); | |
ss << cwd << "/" << name << ".so"; | |
#endif | |
_path = ss.str(); | |
} | |
void DynamicLibrary::load() | |
{ | |
// TODO: Cross-platform error handling | |
#ifdef _MSC_VER | |
_handle = LoadLibrary(_path.c_str()); | |
#else | |
_handle = dlopen(_path.c_str(), RTLD_NOW); | |
#endif | |
} | |
void DynamicLibrary::unload() | |
{ | |
// TODO: Cross-platform error handling | |
#ifdef _MSC_VER | |
FreeLibrary((HINSTANCE)_handle); | |
#else | |
dlclose(_handle); | |
#endif | |
} | |
void* DynamicLibrary::getFunctionAddr(const std::string& name) | |
{ | |
// TODO: POSIX error handling | |
#ifdef _MSC_VER | |
void* func = (void*)GetProcAddress((HINSTANCE)_handle, name.c_str()); | |
if (func == nullptr) | |
{ | |
std::stringstream ss; | |
ss << __func__ << ": Could not find function \"" << name << "\"" | |
throw std::runtime_error(ss.str().c_str()); | |
} | |
return func; | |
#else | |
return dlsym(_handle, name.c_str()); | |
#endif | |
} |
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 | |
#include <string> | |
#include <functional> | |
class DynamicLibrary | |
{ | |
public: | |
explicit DynamicLibrary(const std::string& name); | |
void load(); | |
void unload(); | |
void* getFunctionAddr(const std::string& name); | |
template <typename Func> | |
std::function<Func> getFunction(const std::string& name) | |
{ | |
return std::function<Func>(static_cast<Func*>(getFunctionAddr(name))); | |
} | |
template <typename Ret, typename... Args> | |
Ret callFunction(const std::string& name, Args... args) | |
{ | |
return getFunction<Ret(Args...)>(name)(args...); | |
} | |
inline const std::string& getName() | |
{ | |
return _name; | |
} | |
inline const std::string& getPath() | |
{ | |
return _path; | |
} | |
inline void* getRawHandle() | |
{ | |
return _handle; | |
} | |
private: | |
std::string _name; | |
std::string _path; | |
void* _handle; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment