/dylib

C++ cross-platform wrapper around dynamic loading of shared libraries (dll, so, dylib)

Primary LanguageC++MIT LicenseMIT

dylib

version license cpp

ci coverage

The goal of this C++ library is to load dynamic libraries (.so, .dll, .dylib) and access its functions and global variables at runtime.

⭐ Don't forget to put a star if you like the project!

Compatibility

Works on Linux, MacOS and Windows

Installation

Using a package manager

You can install dylib from vcpkg or conan center:

vcpkg install dylib
conan install --requires=dylib/2.2.1

Using CMake Fetch

You can also fetch dylib to your project using CMake:

include(FetchContent)

FetchContent_Declare(
    dylib
    GIT_REPOSITORY "https://github.com/martin-olivier/dylib"
    GIT_TAG        "v2.2.1"
)

FetchContent_MakeAvailable(dylib)

Documentation

Constructor

The dylib class can load a dynamic library from the system library path

// Load "foo" library from the system library path

dylib lib("foo");

The dylib class can also load a dynamic library from a specific path

// Load "foo" library from relative path "./libs"

dylib lib("./libs", "foo");

// Load "foo" library from full path "/usr/lib"

dylib lib("/usr/lib", "foo");

The dylib class will automatically add the filename decorations of the current os to the library name, but you can disable that by setting decorations parameter to dylib::no_filename_decorations

// Windows -> "foo.dll"
// MacOS   -> "libfoo.dylib"
// Linux   -> "libfoo.so"

dylib lib("foo");

// Windows -> "foo.lib"
// MacOS   -> "foo.lib"
// Linux   -> "foo.lib"

dylib lib("foo.lib", dylib::no_filename_decorations);

Get a function or a variable

get_function
Get a function from the dynamic library currently loaded in the object

get_variable
Get a global variable from the dynamic library currently loaded in the object

// Load "foo" dynamic library

dylib lib("foo");

// Get the function "adder" (get_function<T> will return T*)

auto adder = lib.get_function<double(double, double)>("adder");

// Get the variable "pi_value" (get_variable<T> will return T&)

double pi = lib.get_variable<double>("pi_value");

// Use the function "adder" with "pi_value"

double result = adder(pi, pi);

Miscellaneous tools

has_symbol
Returns true if the symbol passed as parameter exists in the dynamic library, false otherwise

get_symbol
Get a symbol from the dynamic library currently loaded in the object

native_handle
Returns the dynamic library handle

dylib lib("foo");

if (lib.has_symbol("GetModule") == false)
    std::cerr << "symbol 'GetModule' not found in 'foo' lib" << std::endl;

dylib::native_handle_type handle = lib.native_handle();
dylib::native_symbol_type symbol = lib.get_symbol("GetModule");

assert(handle != nullptr && symbol != nullptr);
assert(symbol == dlsym(handle, "GetModule"));

Exceptions

load_error
This exception is raised when the library failed to load or the library encountered symbol resolution issues

symbol_error
This exception is raised when the library failed to load a symbol

Those exceptions inherit from dylib::exception

try {
    dylib lib("foo");
    double pi_value = lib.get_variable<double>("pi_value");
    std::cout << pi_value << std::endl;
} catch (const dylib::load_error &) {
    std::cerr << "failed to load 'foo' library" << std::endl;
} catch (const dylib::symbol_error &) {
    std::cerr << "failed to get 'pi_value' symbol" << std::endl;
}

Example

A full example about the usage of the dylib library is available HERE

Tests

To build unit tests, enter the following commands:

cmake . -B build -DDYLIB_BUILD_TESTS=ON
cmake --build build

To run unit tests, enter the following command inside build directory:

ctest

Community

If you have any question about the usage of the library, do not hesitate to open a discussion

If you want to report a bug or provide a feature, do not hesitate to open an issue or submit a pull request

Contributing

Set the cmake flag DYLIB_BUILD_TESTS to ON to enable tests and make it easier for you to contribute

cmake . -B build -DDYLIB_BUILD_TESTS=ON

Do not forget to sign your commits and use conventional commits when providing a pull request

git commit -s -m "feat: ..."