dylib C++ Library

repository·main·Indexed 19 days ago

https://github.com/martin-olivier/dylib

A C++ library for loading dynamic libraries (.so, .dll, .dylib) at runtime to access C and C++ functions and global variables. It provides tools for symbol resolution, OS-specific filename decorations, and native handle access, with support for installation via vcpkg, conan, or CMake FetchContent.

Tokens
1.6K
Snippets
9
Records
9
Agent score
16%

What's inside dylib

  1. Install dylib using CMake FetchContent

    main

    To integrate dylib directly into your CMake project, use FetchContent to download and make the library available.

    include(FetchContent)
    
    FetchContent_Declare(
        dylib
        GIT_REPOSITORY "https://github.com/martin-olivier/dylib"
        GIT_TAG        "v3.1.0"
    )
    
    FetchContent_MakeAvailable(dylib)
  2. Build and run the dylib example

    main

    To build and run the provided example project using CMake, follow these steps from within the example directory:

    1. Build the project

    Generate the build files and compile the project:

    cmake . -B build
    cmake --build build

    2. Run the executable

    Depending on your operating system, run the command from the appropriate directory:

    On Unix: Run from inside the build folder:

    ./dylib_example

    On Windows: Run from inside the build/Debug folder:

    ./dylib_example.exe
    # Build commands
    cmake . -B build
    cmake --build build
    
    # Run command (Unix)
    ./dylib_example
    
    # Run command (Windows)
    ./dylib_example.exe
  3. Access native handles and symbols

    main

    For low-level access, use native_handle() to get the OS-specific library handle and get_symbol() to get a dylib::native_symbol_type (compatible with dlsym).

    dylib::native_handle_type handle = lib.native_handle();
    dylib::native_symbol_type symbol = lib.get_symbol("pi_value");
  4. Initialize dylib::library with decorations

    main

    The dylib::library class loads dynamic libraries (.so, .dll, .dylib) from relative or full paths. You can use dylib::decorations to handle OS-specific filename prefixes and extensions.

    • Use dylib::decorations::os_default() to automatically apply standard OS decorations (e.g., libfoo.so on Linux, foo.dll on Windows).
    • Use dylib::decorations to define custom prefix/suffix mappings for different operating systems.
    // Load with default OS decorations
    dylib::library lib("./foo", dylib::decorations::os_default());
    
    // Custom decorations
    auto custom_decorations = dylib::decorations(
        DYLIB_WIN_OTHER("", "lib"), 
        DYLIB_WIN_OTHER(".dll", ".so")
    );
    dylib::library lib("./foo", custom_decorations);
  5. Gather library symbols and sections

    main

    You can inspect the contents of a loaded library using symbols() and sections().

    • symbols(): Returns an iterable collection of symbols. Each symbol has a demangled_name and a loadable boolean.
    • sections(): Returns an iterable collection of section names.
    // Iterate through symbols
    for (auto &symbol : lib.symbols()) {
        if (symbol.loadable)
            std::cout << symbol.demangled_name << std::endl;
    }
    
    // Iterate through sections
    for (auto &section : lib.sections()) {
        std::cout << section << std::endl;
    }
  6. Get C++ functions and variables

    main

    To access C++ symbols, provide the fully qualified name including namespaces. For functions, the name string must follow the format: namespace::function_name(argument_types) where argument types include qualifiers like const, volatile, *, &, or &&.

    dylib::library lib("./foo", dylib::decorations::os_default());
    
    // Get C++ function in namespace "tools"
    auto int_to_string = lib.get_function<std::string(int)>("tools::to_string(int)");
    
    // Get variable in namespace "global::math"
    double pi = lib.get_variable<double>("global::math::pi_value");
    
    std::string s = int_to_string(42);
  7. Get C functions and variables

    main

    Use get_function<T> to retrieve a function pointer and get_variable<T> to retrieve a reference to a global variable from a loaded library.

    • get_function<T>(name): Returns a pointer of type T*.
    • get_variable<T>(name): Returns a reference of type T&.
    dylib::library lib("./foo", dylib::decorations::os_default());
    
    // Get a C function "adder"
    auto adder = lib.get_function<double(double, double)>("adder");
    
    // Get a variable "pi_value"
    double pi = lib.get_variable<double>("pi_value");
    
    double result = adder(pi, pi);
  8. Handle dylib exceptions

    main

    All dylib exceptions inherit from dylib::exception. Common error types include:

    • dylib::load_error: Raised when the library fails to load or encounters symbol resolution issues.
    • dylib::symbol_error: Raised when a specific symbol cannot be loaded.
    • dylib::collection_error: Raised when failing to collect lists like symbols or sections.
    try {
        dylib::library lib("./foo", dylib::decorations::os_default());
        double pi = lib.get_variable<double>("pi_value");
    } catch (const dylib::load_error &) {
        // Handle load failure
    } catch (const dylib::symbol_error &) {
        // Handle symbol resolution failure
    }