Mercurial > code
changeset 195:42b77e0161d0
Add a dynamic library loader
author | David Demelier <markand@malikania.fr> |
---|---|
date | Wed, 27 Nov 2013 21:20:26 +0100 |
parents | 9fc5f917872b |
children | 274b4f216e65 |
files | C++/DynLib.cpp C++/DynLib.h |
diffstat | 2 files changed, 200 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/C++/DynLib.cpp Wed Nov 27 21:20:26 2013 +0100 @@ -0,0 +1,105 @@ +/* + * DynLib.cpp -- portable shared library loader + * + * Copyright (c) 2013 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <stdexcept> + +#if defined(_MSC_VER) +# include <Windows.h> +#else +# include <dlfcn.h> +#endif + +#include "DynLib.h" + +#if defined(_MSC_VER) + +void DynLib::systemInit() +{ + // TODO: Windows +} + +DynLib::Handle DynLib::systemLoad(const std::string &path, Policy policy); +{ + // TODO: Windows +} + +DynLib::Sym DynLib::systemSym(const std::string &name) +{ + // TODO: Windows +} + +void DynLib::systemClose() +{ + // TODO: Windows +} + +#else + +void DynLib::systemInit() +{ + m_handle = nullptr; +} + +DynLib::Handle DynLib::systemLoad(const std::string &path, Policy policy) const +{ + int mode = (policy == Immediately) ? RTLD_NOW : RTLD_LAZY; + Handle handle; + + handle = dlopen(path.c_str(), mode); + if (handle == nullptr) + throw std::runtime_error(dlerror()); + + return handle; +} + +DynLib::Sym DynLib::systemSym(const std::string &name) +{ + Sym sym; + + if (m_handle == nullptr) + throw std::runtime_error("library not loaded"); + + sym = dlsym(m_handle, name.c_str()); + if (sym == nullptr) + throw std::out_of_range(dlerror()); + + return sym; +} + +void DynLib::systemClose() +{ + if (m_handle != nullptr) + dlclose(m_handle); +} + +#endif + +DynLib::DynLib() +{ + systemInit(); +} + +DynLib::DynLib(const std::string &path, Policy policy) +{ + m_handle = systemLoad(path, policy); +} + +DynLib::~DynLib() +{ + systemClose(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/C++/DynLib.h Wed Nov 27 21:20:26 2013 +0100 @@ -0,0 +1,95 @@ +/* + * DynLib.h -- portable shared library loader + * + * Copyright (c) 2013 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _DYN_LIB_H_ +#define _DYN_LIB_H_ + +#include <string> + +/** + * @class DynLib + * @brief Load a dynamic module + * + * This class is a portable wrapper to load shared libraries on + * supported systems. + */ +class DynLib { +public: +#if defined(_MSC_VER) +#else + using Handle = void *; + using Sym = void *; +#endif + + enum Policy { + Immediately, //! load symbols immediately + Lazy //! load symbols when needed + }; + +private: + Handle m_handle; + + void systemInit(); + Handle systemLoad(const std::string &path, Policy policy) const; + Sym systemSym(const std::string &name); + void systemClose(); + +public: + /** + * Copy is forbidden. + */ + DynLib(const DynLib &) = delete; + DynLib &operator=(const DynLib &) = delete; + + /** + * Default constructor. + */ + DynLib(); + + /** + * Constructor to load a shared module. The path must + * be absolute. + * + * @param path the absolute path + * @param policy the policy to load + * @throw std::runtime_error on error + */ + DynLib(const std::string &path, + Policy policy = Immediately); + + /** + * Close the library automatically. + */ + ~DynLib(); + + /** + * Get a symbol from the library. + * + * @param name the symbol + * @return the symbol + * @throw std::runtime_error on error + * @throw std::out_of_range if not found + */ + template <typename T> + T sym(const std::string &name) + { + return reinterpret_cast<T>(systemSym(name)); + } +}; + +#endif // !_DYN_LIB_H_