From 48f3a78c28169ac9a0b3c7235553a86a90851027 Mon Sep 17 00:00:00 2001 From: Martin Olivier <58467105+martin-olivier@users.noreply.github.com> Date: Mon, 7 Feb 2022 00:53:33 +0100 Subject: [PATCH] Version 1.8.0 (#10) # Changelog - feat: `has_symbol` function - feat: `operator bool()` - feat: Valgrind CI # Examples ## has_symbol ```c++ void dylib_symbol_example(const dylib &lib) { if (lib.has_symbol("GetModule")) std::cout << "GetModule has been found" << std::endl; else std::cout << "Could not found GetModule symbol" << std::endl; } ``` ## operator bool() ```c++ void dylib_status_example(const dylib &lib) { if (lib) std::cout << "something is curently loaded in the dylib object" << std::endl; if (!lib) std::cout << "nothing is curently loaded in the dylib object" << std::endl; } ``` --- .github/workflows/CI.yml | 24 +++++++++++++++++++++++- README.md | 9 ++++++--- dylib.hpp | 40 +++++++++++++++++++++++++++++++++++----- tests/tests.cpp | 25 +++++++++++++++++++++++++ 4 files changed, 89 insertions(+), 9 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 7dd864a..bfdb517 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -1,6 +1,6 @@ name: CI -on: [push] +on: [push, pull_request] defaults: run: @@ -41,3 +41,25 @@ jobs: - name: Send Coverage to codecov.io if: ${{ matrix.os == 'ubuntu-latest' }} run: bash <(curl -s https://codecov.io/bash) + + memory_check: + name: memory check + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Update Packages + run: sudo apt update + + - name: Install Valgrind + run: sudo apt install -y valgrind + + - name: Generate Tests Build File + run: cmake . -B build -DBUILD_TESTS=ON -DCMAKE_BUILD_TYPE=Debug + + - name: Build Unit Tests + run: cmake --build build + + - name: Run Unit Tests with Valgrind + run: valgrind --leak-check=full --show-leak-kinds=all --error-exitcode=1 ./unit_tests \ No newline at end of file diff --git a/README.md b/README.md index 5431cc1..d307b51 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Dylib - Dynamic Library Loader for C++ -[![Dylib](https://img.shields.io/badge/Dylib-v1.7.1-blue.svg)](https://github.com/martin-olivier/dylib/releases/tag/v1.7.1) +[![Dylib](https://img.shields.io/badge/Dylib-v1.8.0-blue.svg)](https://github.com/martin-olivier/dylib/releases/tag/v1.8.0) [![MIT license](https://img.shields.io/badge/License-MIT-orange.svg)](https://github.com/martin-olivier/dylib/blob/main/LICENSE) [![CPP Version](https://img.shields.io/badge/C++-11_and_above-darkgreen.svg)](https://isocpp.org/) @@ -10,7 +10,7 @@ [![workflow](https://github.com/martin-olivier/dylib/actions/workflows/CI.yml/badge.svg)](https://github.com/martin-olivier/dylib/actions/workflows/CI.yml) [![codecov](https://codecov.io/gh/martin-olivier/dylib/branch/main/graph/badge.svg?token=4V6A9B7PII)](https://codecov.io/gh/martin-olivier/dylib) -[![GitHub download](https://img.shields.io/github/downloads/martin-olivier/dylib/total?style=for-the-badge)](https://github.com/martin-olivier/dylib/releases/download/v1.7.1/dylib.hpp) +[![GitHub download](https://img.shields.io/github/downloads/martin-olivier/dylib/total?style=for-the-badge)](https://github.com/martin-olivier/dylib/releases/download/v1.8.0/dylib.hpp) The goal of this C++ Library is to load dynamic libraries (.so, .dll, .dylib) and access its functions and global variables at runtime. @@ -19,7 +19,7 @@ Works on `Linux`, `Windows`, `MacOS` # Installation -Click [HERE](https://github.com/martin-olivier/dylib/releases/download/v1.7.1/dylib.hpp) to download the dylib header file +Click [HERE](https://github.com/martin-olivier/dylib/releases/download/v1.8.0/dylib.hpp) to download the dylib header file `⭐ Don't forget to put a star if you like the project!` # Documentation @@ -63,6 +63,9 @@ lib.close(); ## Get a Function or a Variable +`has_symbol` +Check if a symbol exists in the currently loaded dynamic library. + `get_function` Get a function from the dynamic library currently loaded in the object. diff --git a/dylib.hpp b/dylib.hpp index b9c694c..1139353 100644 --- a/dylib.hpp +++ b/dylib.hpp @@ -2,7 +2,7 @@ * \file dylib.hpp * \brief Cross-platform Dynamic Library Loader * \author Martin Olivier - * \version 1.7.1 + * \version 1.8.0 * * MIT License * Copyright (c) 2022 Martin Olivier @@ -93,9 +93,9 @@ class dylib return msg; return msg + '\n' + err; } - static std::string get_missing_handle_error(const std::string &name) + static std::string get_missing_handle_error(const std::string &symbol_name) { - return "dylib: could not get symbol \"" + name + "\", no dynamic library loaded"; + return "dylib: could not get symbol \"" + symbol_name + "\", no dynamic library currently loaded"; } public: @@ -229,7 +229,7 @@ class dylib * it must be the same pattern as the template of std::function * @param name the symbol name of the function to get from the dynamic library * - * @returns std::function that contains the function + * @return std::function that contains the function */ template std::function get_function(const char *name) const @@ -256,7 +256,7 @@ class dylib * @param T type of the global variable * @param name the name of the global variable to get from the dynamic library * - * @returns global variable of type + * @return global variable of type */ template T &get_variable(const char *name) const @@ -277,6 +277,36 @@ class dylib return get_variable(name.c_str()); } + /** + * Check if a symbol exists in the currently loaded dynamic library. + * This method will return false if no dynamic library is currently loaded or if the symbol equals nullptr + * + * @param symbol the symbol name to look for + * + * @return true if the symbol exists in the dynamic library, false otherwise + */ + bool has_symbol(const char *symbol) const noexcept + { + if (!m_handle) + return false; + if (!symbol) + return false; + return get_symbol(symbol) != nullptr; + } + + bool has_symbol(const std::string &symbol) const noexcept + { + return has_symbol(symbol.c_str()); + } + + /** + * @return true if a dynamic library is currently loaded in the object, false otherwise + */ + operator bool() const noexcept + { + return m_handle != nullptr; + } + /** * Close the dynamic library currently loaded in the object. * This function will be automatically called by the class destructor diff --git a/tests/tests.cpp b/tests/tests.cpp index 15fb965..1461dcc 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -230,6 +230,31 @@ TEST(std_move, basic_test) } } +TEST(has_symbol, basic_test) +{ + dylib lib; + EXPECT_FALSE(lib.has_symbol(nullptr)); + EXPECT_FALSE(lib.has_symbol("pi_value")); + lib.open("./dynamic_lib", dylib::extension); + EXPECT_TRUE(lib.has_symbol("pi_value")); + EXPECT_FALSE(lib.has_symbol("bad_symbol")); + lib.close(); + EXPECT_FALSE(lib.has_symbol("pi_value")); +} + +TEST(operator_bool, basic_test) +{ + dylib lib; + EXPECT_FALSE(lib); + EXPECT_TRUE(!lib); + lib.open("./dynamic_lib", dylib::extension); + EXPECT_TRUE(lib); + EXPECT_FALSE(!lib); + lib.close(); + EXPECT_TRUE(!lib); + EXPECT_FALSE(lib); +} + int main(int ac, char **av) { testing::InitGoogleTest(&ac, av);