A header-only C++ library for dynamic loading utilities that provides safe and convenient wrappers around dlopen/dlsym for dynamically loading shared libraries at runtime.
- Header-only: Easy integration with no linking required
- Type-safe: Template-based design ensures compile-time type checking
- Exception-based error handling: Errors are reported via
std::runtime_errorwith descriptive messages including file, line, and cause - RAII-compliant: Automatic resource management (libraries are automatically closed on destruction)
- Lightweight: Minimal overhead and dependencies
- Thread-aware: Designed with threading considerations (note:
dlopen/dlsymoperations are not thread-safe)
- C++17 compatible compiler
- CMake 3.20 or higher
- POSIX-compliant system with
dlfcn.h(Linux, macOS, etc.)
Simply copy the include/dlutils directory into your project and include the header:
#include "dlutils/dlutils.hpp"Add this repository as a submodule or download the source, then in your CMakeLists.txt:
add_subdirectory(dlutils-cpp)
target_link_libraries(your_target PRIVATE dlutils-cpp)Here's a simple example showing how to load OpenSSL functions dynamically:
#include "dlutils/dlutils.hpp"
class LibCrypto : public dlutils::DlLibBase {
public:
// Declare the functions you want to load
dlutils::DlFun<EVP_MD_CTX*> EVP_MD_CTX_new;
dlutils::DlFun<const EVP_MD*> EVP_sha256;
static LibCrypto& GetInstance() {
static LibCrypto instance;
return instance;
}
private:
void LoadAll() {
SelfDlOpen(); // Load the library
DLUTILS_SELF_DLSYM(EVP_MD_CTX_new); // Load function
DLUTILS_SELF_DLSYM(EVP_sha256); // Load function
}
LibCrypto() : DlLibBase("libcrypto.so") {
LoadAll(); // Functions are loaded in constructor
}
};
// Usage - All errors are reported via std::runtime_error
try {
auto& libcrypto = LibCrypto::GetInstance();
// Use the functions safely - library and functions are already loaded
EVP_MD_CTX* ctx = libcrypto.EVP_MD_CTX_new();
const EVP_MD* md = libcrypto.EVP_sha256();
// ... use ctx and md ...
} catch (const std::runtime_error& e) {
// Handle library loading or function loading errors
std::cerr << "Error: " << e.what() << std::endl;
}For a complete working example, see test/openssl.hpp and test/openssl_test.cpp.
mkdir build && cd build
cmake ..
makemkdir build && cd build
cmake ..
make
ctest
# Or run specific test
./openssl_testmkdir build && cd build
cmake -DENABLE_COVERAGE=ON ..
make
ctest # Run tests to generate coverage data
make coverage # Generate coverage reportIf lcov is installed, open coverage_report/index.html in your browser to view the report.
Otherwise, gcov files will be generated in the gcov_report directory.
This project uses GitHub Actions for continuous integration. Code coverage reports are automatically generated for each pull request and push to the main branch. You can view the reports by downloading the artifacts from the workflow runs.
- Add a new
DlFun<>member to your library class with the correct function signature - Add the function name to the
LoadAll()method usingDLUTILS_SELF_DLSYM(NAME)
// Add declaration
DlFun<int, const char*> MyNewFunction;
// Add to LoadAll()
void LoadAll() {
SelfDlOpen();
DLUTILS_SELF_DLSYM(MyNewFunction); // <-- Add this line
}- Create a new class inheriting from
DlLibBase - Define
DlFunmembers for each function you want to load - Implement a
LoadAll()method to callSelfDlOpen()and load all functions viaDLUTILS_SELF_DLSYM - Call
LoadAll()in your constructor (lazily load on first use, or eagerly load during construction)
class MyLib : public dlutils::DlLibBase {
public:
DlFun<void> some_function;
DlFun<int> another_function;
static MyLib& GetInstance() {
static MyLib instance;
return instance;
}
private:
void LoadAll() {
SelfDlOpen();
DLUTILS_SELF_DLSYM(some_function);
DLUTILS_SELF_DLSYM(another_function);
}
MyLib() : DlLibBase("libmylib.so") {
LoadAll();
}
};For detailed architecture diagrams and flowcharts, see the docs/ directory:
- architecture.puml - Class architecture diagram
- loading-flow.puml - Library loading flowchart
- usage-sequence.puml - Runtime usage sequence diagram
See docs/README.md for instructions on rendering PlantUML diagrams.
This project is licensed under the MIT License - see the LICENSE file for details.