Skip to content

Instantly share code, notes, and snippets.

@TheBurnDoc
Last active December 30, 2015 09:08
Show Gist options
  • Save TheBurnDoc/7806867 to your computer and use it in GitHub Desktop.
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 ...).
#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
}
#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