From 2a9b4d59d889979d7dc390b6a074b75720b4b60c Mon Sep 17 00:00:00 2001 From: Martin Olivier <58467105+tocola@users.noreply.github.com> Date: Wed, 12 Jan 2022 17:17:11 +0100 Subject: [PATCH] Version 1.7.0 (#8) feat: cross-platform DYLIB_API macro feat: the library is now in snake_case fix: documentation fix: win32 check on CMakeLists fix: license up-to-date Co-authored-by: @MaximeHouis --- .github/workflows/{unit_tests.yml => CI.yml} | 19 +-- CMakeLists.txt | 46 +++--- LICENSE | 2 +- README.md | 131 ++++++++++-------- cmake/BuildDynLib.cmake | 10 -- DyLib.hpp => dylib.hpp | 127 ++++++++--------- .../FetchGoogleTest.cmake | 4 +- test/myDynLib.cpp | 21 ++- test/tests.cpp | 120 ++++++++-------- 9 files changed, 233 insertions(+), 247 deletions(-) rename .github/workflows/{unit_tests.yml => CI.yml} (67%) delete mode 100644 cmake/BuildDynLib.cmake rename DyLib.hpp => dylib.hpp (62%) rename cmake/FindGTest.cmake => import/FetchGoogleTest.cmake (63%) diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/CI.yml similarity index 67% rename from .github/workflows/unit_tests.yml rename to .github/workflows/CI.yml index 01d4038..3b58147 100644 --- a/.github/workflows/unit_tests.yml +++ b/.github/workflows/CI.yml @@ -8,7 +8,6 @@ defaults: jobs: run_unit_tests: - strategy: fail-fast: false matrix: @@ -16,13 +15,13 @@ jobs: include: - os: windows-latest bin: unit_tests.exe - dir: Debug + dir: ./Debug/ - os: ubuntu-latest bin: unit_tests - dir: . + dir: ./ - os: macos-latest bin: unit_tests - dir: . + dir: ./ name: Unit Tests runs-on: ${{ matrix.os }} @@ -30,20 +29,14 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Create Build Directory - run: mkdir build - - name: Generate Project Files - working-directory: build - run: cmake -DCMAKE_BUILD_TYPE=Release .. + run: cmake . -B build/ -DCMAKE_BUILD_TYPE=Release - name: Build Dynamic Library and Unit Tests - working-directory: build - run: cmake --build . + run: cmake --build build/ - name: Run Unit Tests - working-directory: ${{ matrix.dir }} - run: ./${{ matrix.bin }} + run: ${{ matrix.dir }}${{ matrix.bin }} - name: Send Coverage to codecov.io if: ${{ matrix.os == 'ubuntu-latest' }} diff --git a/CMakeLists.txt b/CMakeLists.txt index 364e5eb..9069856 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.14) -project(DyLib) +project(dylib) set(CMAKE_VERBOSE_MAKEFILE off) @@ -12,43 +12,37 @@ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}) option(WITH_TESTS "Enable testing" ON) if(WITH_TESTS) -include(cmake/FindGTest.cmake) +include(import/FetchGoogleTest.cmake) -if (UNIX) +if(UNIX) add_compile_options(-Wall -Wextra -Weffc++) -else () +elseif(WIN32) add_compile_options(/W4) endif() -include(cmake/BuildDynLib.cmake) - -if (UNIX AND NOT APPLE) - add_compile_options(--coverage) -endif() +add_library(dynlib SHARED test/myDynLib.cpp) +target_include_directories(dynlib PRIVATE .) +set_target_properties(dynlib PROPERTIES PREFIX "") enable_testing() -add_executable(unit_tests - test/tests.cpp) +add_executable(unit_tests test/tests.cpp) target_include_directories(unit_tests PRIVATE .) -if (UNIX AND NOT APPLE) - target_link_libraries(unit_tests PRIVATE - gcov - ) +if(UNIX AND NOT APPLE) + add_compile_options(--coverage) + target_link_libraries(unit_tests PRIVATE gcov) endif() -if (UNIX) +if(UNIX) target_link_libraries(unit_tests PRIVATE - dl - pthread + dl + pthread ) endif() -target_link_libraries(unit_tests PRIVATE - gtest_main -) +target_link_libraries(unit_tests PRIVATE gtest_main) include(GoogleTest) @@ -57,11 +51,11 @@ gtest_discover_tests(unit_tests) add_dependencies(unit_tests dynlib) endif(WITH_TESTS) -set(CPACK_PACKAGE_NAME "DyLib") +set(CPACK_PACKAGE_NAME "dylib") set(CPACK_PACKAGE_VENDOR "Martin Olivier") set(CPACK_PACKAGE_VERSION_MAJOR "1") -set(CPACK_PACKAGE_VERSION_MINOR "6") -set(CPACK_PACKAGE_VERSION_PATCH "2") +set(CPACK_PACKAGE_VERSION_MINOR "7") +set(CPACK_PACKAGE_VERSION_PATCH "0") set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}") set(CPACK_PACKAGE_DESCRIPTION "Cross-platform Dynamic Library Loader for C++") set(CPACK_DEBIAN_PACKAGE_NAME "${CPACK_PACKAGE_NAME}") @@ -72,7 +66,7 @@ include(CMakePackageConfigHelpers) set(PackagingTemplatesDir "${CMAKE_CURRENT_SOURCE_DIR}/packaging") -set(LIB_NAME "DyLib") +set(LIB_NAME "dylib") string(TOUPPER "${LIB_NAME}" LIB_NAME_UPPER) set(CMAKE_EXPORT_NAME "${LIB_NAME}") set(PKG_CONFIG_NAME "${LIB_NAME}") @@ -123,7 +117,7 @@ set("CPACK_RPM_DEV_PACKAGE_SUGGESTS" "${CPACK_DEBIAN_DEV_PACKAGE_SUGGESTS}") set(CPACK_COMPONENTS_ALL "dev") -set(CPACK_PACKAGE_HOMEPAGE_URL "https://github.com/tocola/DyLib") +set(CPACK_PACKAGE_HOMEPAGE_URL "https://github.com/tocola/dylib") set(CPACK_PACKAGE_MAINTAINER "${CPACK_PACKAGE_VENDOR}") set(CPACK_DEBIAN_PACKAGE_MAINTAINER "${CPACK_PACKAGE_MAINTAINER}") set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") diff --git a/LICENSE b/LICENSE index e5b2b0b..1cc14c8 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021 Martin Olivier +Copyright (c) 2022 Martin Olivier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 654986e..1901e3b 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,16 @@ -# DyLib - Dynamic Library Loader for C++ -[![DyLib](https://img.shields.io/badge/DyLib-v1.6.2-blue.svg)](https://github.com/tocola/DyLib/releases/tag/v1.6.2) -[![MIT license](https://img.shields.io/badge/License-MIT-orange.svg)](https://github.com/tocola/DyLib/blob/main/LICENSE) -[![CPP Version](https://img.shields.io/badge/C++-11/14/17/20-darkgreen.svg)](https://isocpp.org/) +# Dylib - Dynamic Library Loader for C++ +[![Dylib](https://img.shields.io/badge/Dylib-v1.7.0-blue.svg)](https://github.com/tocola/dylib/releases/tag/v1.7.0) +[![MIT license](https://img.shields.io/badge/License-MIT-orange.svg)](https://github.com/tocola/dylib/blob/main/LICENSE) +[![CPP Version](https://img.shields.io/badge/C++-11_and_above-darkgreen.svg)](https://isocpp.org/) -[![GitHub watchers](https://img.shields.io/github/watchers/tocola/DyLib?style=social)](https://github.com/tocola/DyLib/watchers/) -[![GitHub forks](https://img.shields.io/github/forks/tocola/DyLib?style=social)](https://github.com/tocola/DyLib/network/members/) -[![GitHub stars](https://img.shields.io/github/stars/tocola/DyLib?style=social)](https://github.com/tocola/DyLib/stargazers/) +[![GitHub watchers](https://img.shields.io/github/watchers/tocola/dylib?style=social)](https://github.com/tocola/dylib/watchers/) +[![GitHub forks](https://img.shields.io/github/forks/tocola/dylib?style=social)](https://github.com/tocola/dylib/network/members/) +[![GitHub stars](https://img.shields.io/github/stars/tocola/dylib?style=social)](https://github.com/tocola/dylib/stargazers/) -[![workflow](https://github.com/tocola/DyLib/actions/workflows/unit_tests.yml/badge.svg)](https://github.com/tocola/DyLib/actions/workflows/unit_tests.yml) -[![codecov](https://codecov.io/gh/tocola/DyLib/branch/main/graph/badge.svg?token=4V6A9B7PII)](https://codecov.io/gh/tocola/DyLib) +[![workflow](https://github.com/tocola/dylib/actions/workflows/CI.yml/badge.svg)](https://github.com/tocola/dylib/actions/workflows/CI.yml) +[![codecov](https://codecov.io/gh/tocola/dylib/branch/main/graph/badge.svg?token=4V6A9B7PII)](https://codecov.io/gh/tocola/dylib) -[![GitHub download](https://img.shields.io/github/downloads/tocola/DyLib/total?style=for-the-badge)](https://github.com/tocola/DyLib/releases/download/v1.6.2/DyLib.hpp) +[![GitHub download](https://img.shields.io/github/downloads/tocola/dylib/total?style=for-the-badge)](https://github.com/tocola/dylib/releases/download/v1.7.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,38 +19,38 @@ Works on `Linux`, `Windows`, `MacOS` # Installation -Click [HERE](https://github.com/tocola/DyLib/releases/download/v1.6.2/DyLib.hpp) to download the DyLib header file -`Don't forget to put a star on the project 🌟` +Click [HERE](https://github.com/tocola/dylib/releases/download/v1.7.0/dylib.hpp) to download the dylib header file +`⭐ Don't forget to put a star if you like the project!` # Documentation -## DyLib Class +## Dylib Class -The DyLib class can load a dynamic library at runtime : +The dylib class can load a dynamic library at runtime: ```c++ -DyLib lib("./myDynLib.so"); +dylib lib("./myDynLib.so"); ``` -The DyLib class can detect the file extension of the actual os using `DyLib::extension` : +The dylib class can detect the file extension of the actual os using `dylib::extension`: ```c++ -DyLib lib("./myDynLib", DyLib::extension); +dylib lib("./myDynLib", dylib::extension); ``` or ```c++ -DyLib lib; -lib.open("./myDynLib", DyLib::extension); +dylib lib; +lib.open("./myDynLib", dylib::extension); ``` ## Open and Close `open` -Load a dynamic library into the object. If a dynamic library was already opened, it will be unload and replaced +Load a dynamic library into the object. If a dynamic library was already opened, it will be unloaded and replaced `close` Close the dynamic library currently loaded in the object. This function will be automatically called by the class destructor ```c++ // Load ./myDynLib.so -DyLib lib("./myDynLib.so"); +dylib lib("./myDynLib.so"); // Unload ./myDynLib.so and load ./otherLib.so @@ -63,107 +63,106 @@ lib.close(); ## Get a Function or a Variable -`getFunction` +`get_function` Get a function from the dynamic library currently loaded in the object. -`getVariable` +`get_variable` Get a global variable from the dynamic library currently loaded in the object. ```c++ // Load ./myDynLib.so -DyLib lib("./myDynLib.so"); +dylib lib("./myDynLib.so"); // Get the global function adder -auto adder = lib.getFunction("adder"); +auto adder = lib.get_function("adder"); // Get the global variable pi_value -double pi = lib.getVariable("pi_value"); +double pi = lib.get_variable("pi_value"); // Use the function adder with pi_value double result = adder(pi, pi); ``` -## DyLib Exceptions +## Dylib Exceptions `handle_error` -This exception is thrown when the library failed to load or the library encountered symbol resolution issues +This exception is raised when the library failed to load or the library encountered symbol resolution issues `symbol_error` -This exception is thrown when the library failed to load a symbol. -This usualy happens when you forgot to mark a library function or variable as `extern "C"` +This exception is raised when the library failed to load a symbol. +This usually happens when you forgot to put `DYLIB_API` before a library function or variable -Those exceptions inherits from `DyLib::exception` +Those exceptions inherit from `dylib::exception` ```c++ try { - DyLib lib("./myDynLib.so"); - double pi_value = lib.getVariable("pi_value"); + dylib lib("./myDynLib.so"); + double pi_value = lib.get_variable("pi_value"); std::cout << pi_value << std::endl; } -catch (const DyLib::exception &e) { +catch (const dylib::exception &e) { std::cerr << e.what() << std::endl; return EXIT_FAILURE; } return EXIT_SUCCESS; ``` -# Exemple +# Example -Lets write some functions in our future dynamic library : +Let's write some functions in our forthcoming dynamic library: ```c++ // myDynLib.cpp #include +#include "dylib.hpp" -extern "C" { - double pi_value = 3.14159; - void *ptr = (void *)1; +DYLIB_API double pi_value = 3.14159; +DYLIB_API void *ptr = (void *)1; - double adder(double a, double b) - { - return a + b; - } +DYLIB_API double adder(double a, double b) +{ + return a + b; +} - void printHello() - { - std::cout << "Hello!" << std::endl; - } +DYLIB_API void print_hello() +{ + std::cout << "Hello!" << std::endl; } ``` -Lets build our code into a dynamic library : +Let's build our code into a dynamic library: `g++ -std=c++11 -fPIC -shared myDynLib.cpp -o myDynLib.so` -Lets try to access the functions and global variables of our dynamic library at runtime with this code : +Let's try to access the functions and global variables of our dynamic library at runtime with this code: ```c++ // main.cpp #include -#include "DyLib.hpp" +#include "dylib.hpp" int main() { try { - DyLib lib("./myDynLib.so"); + dylib lib("./myDynLib.so"); - auto adder = lib.getFunction("adder"); + auto adder = lib.get_function("adder"); std::cout << adder(5, 10) << std::endl; - auto printer = lib.getFunction("printHello"); + auto printer = lib.get_function("print_hello"); printer(); - double pi_value = lib.getVariable("pi_value"); + double pi_value = lib.get_variable("pi_value"); std::cout << pi_value << std::endl; - auto &ptr = lib.getVariable("ptr"); + auto &ptr = lib.get_variable("ptr"); if (ptr == (void *)1) std::cout << "1" << std::endl; } - catch (const DyLib::exception &e) { + catch (const dylib::exception &e) { std::cerr << e.what() << std::endl; return EXIT_FAILURE; } @@ -171,14 +170,30 @@ int main() } ``` -Lets build and run our code : +Let's build and run our code: `g++ -std=c++11 main.cpp -o out -ldl` `./out` -Output : +Output: ``` 15 Hello! 3.14159 1 ``` + +# Tips + +> If you use CMake to build a dynamic library, running the below CMake rule will allow you to remove the prefix `lib` for macOS and linux, ensuring that the library shares the same name on all the different OS: + +```cmake +set_target_properties(target PROPERTIES PREFIX "") +``` + +## Results + +| | Without CMake rule | With CMake rule | +|:-------:|:----------------------|:----------------| +| Linux | ***lib***malloc.so | malloc.so | +| MacOS | ***lib***malloc.dylib | malloc.dylib | +| Windows | malloc.dll | malloc.dll | diff --git a/cmake/BuildDynLib.cmake b/cmake/BuildDynLib.cmake deleted file mode 100644 index cf80be7..0000000 --- a/cmake/BuildDynLib.cmake +++ /dev/null @@ -1,10 +0,0 @@ -cmake_minimum_required(VERSION 3.14) - -if(MSVC) - set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE) -endif() - -add_library(dynlib SHARED - test/myDynLib.cpp) - -set_target_properties(dynlib PROPERTIES PREFIX "") \ No newline at end of file diff --git a/DyLib.hpp b/dylib.hpp similarity index 62% rename from DyLib.hpp rename to dylib.hpp index 5b0eb17..226123a 100644 --- a/DyLib.hpp +++ b/dylib.hpp @@ -1,11 +1,11 @@ /** - * \file DyLib.hpp + * \file dylib.hpp * \brief Cross-platform Dynamic Library Loader * \author Martin Olivier - * \version 1.6.2 + * \version 1.7.0 * * MIT License - * Copyright (c) 2021 Martin Olivier + * Copyright (c) 2022 Martin Olivier */ #pragma once @@ -16,33 +16,36 @@ #include #if defined(_WIN32) || defined(_WIN64) #define WIN32_LEAN_AND_MEAN +#define DYLIB_API extern "C" __declspec(dllexport) #include +#undef WIN32_LEAN_AND_MEAN #else +#define DYLIB_API extern "C" #include #endif /** - * The DyLib class can hold a dynamic library instance and interact with it + * The dylib class can hold a dynamic library instance and interact with it * by getting its symbols like functions or global variables */ -class DyLib +class dylib { private: #if defined(_WIN32) || defined(_WIN64) HINSTANCE m_handle{nullptr}; - static HINSTANCE openLib(const char *path) noexcept + static HINSTANCE open_lib(const char *path) noexcept { return LoadLibraryA(path); } - FARPROC getSymbol(const char *name) const noexcept + FARPROC get_symbol(const char *name) const noexcept { return GetProcAddress(m_handle, name); } - void closeLib() noexcept + void close_lib() noexcept { FreeLibrary(m_handle); } - static char *getErrorMessage() noexcept + static char *get_error_message() noexcept { constexpr size_t bufSize = 512; auto errorCode = GetLastError(); @@ -57,33 +60,33 @@ class DyLib } #else void *m_handle{nullptr}; - static void *openLib(const char *path) noexcept + static void *open_lib(const char *path) noexcept { return dlopen(path, RTLD_NOW | RTLD_LOCAL); } - void *getSymbol(const char *name) const noexcept + void *get_symbol(const char *name) const noexcept { return dlsym(m_handle, name); } - void closeLib() noexcept + void close_lib() noexcept { dlclose(m_handle); } - static char *getErrorMessage() noexcept + static char *get_error_message() noexcept { return dlerror(); } #endif - static std::string getHandleError(const std::string &name) + static std::string get_handle_error(const std::string &name) { - auto err = getErrorMessage(); + auto err = get_error_message(); if (!err) return "error while loading dynamic library \"" + name + "\""; return err; } - static std::string getSymbolError(const std::string &name) + static std::string get_symbol_error(const std::string &name) { - auto err = getErrorMessage(); + auto err = get_error_message(); if (!err) return "error while loading symbol \"" + name + "\""; return err; @@ -100,9 +103,9 @@ class DyLib #endif /** - * This exception is thrown when the DyLib class encountered an error. + * This exception is thrown when the dylib class encountered an error * - * @return error message by calling what() member function + * @return the error message by calling what() member function */ class exception : public std::exception { @@ -115,9 +118,9 @@ class DyLib /** * This exception is thrown when the library failed to load - * or the library encountered symbol resolution issues + * or encountered symbol resolution issues * - * @param message error message + * @param message the error message */ class handle_error : public exception { @@ -127,9 +130,9 @@ class DyLib /** * This exception is thrown when the library failed to load a symbol. - * This usually happens when you forgot to mark a library function or variable as extern "C" + * This usually happens when you forgot to put before a library function or variable * - * @param message error message + * @param message the error message */ class symbol_error : public exception { @@ -137,26 +140,16 @@ class DyLib explicit symbol_error(std::string &&message) : exception(std::move(message)) {} }; - /** - * Creates a dynamic library object - */ - DyLib() noexcept = default; + dylib(const dylib&) = delete; + dylib& operator=(const dylib&) = delete; - DyLib(const DyLib&) = delete; - DyLib& operator=(const DyLib&) = delete; - - /** - * Move constructor : move a dynamic library instance to build this object - * - * @param other ref on rvalue of the other DyLib (use std::move) - */ - DyLib(DyLib &&other) noexcept + dylib(dylib &&other) noexcept { m_handle = other.m_handle; other.m_handle = nullptr; } - DyLib& operator=(DyLib &&other) noexcept + dylib& operator=(dylib &&other) noexcept { if (this != &other) { close(); @@ -166,47 +159,49 @@ class DyLib return *this; } + dylib() noexcept = default; + /** * Creates a dynamic library instance * * @param path path to the dynamic library to load - * @param ext use DyLib::extension to specify the os extension (optional parameter) + * @param ext use dylib::extension to specify the os extension (optional parameter) */ - explicit DyLib(const char *path) + explicit dylib(const char *path) { open(path); } - explicit DyLib(const std::string &path) + explicit dylib(const std::string &path) { open(path.c_str()); } - DyLib(std::string path, const char *ext) + dylib(std::string path, const char *ext) { open(std::move(path), ext); } - ~DyLib() + ~dylib() { close(); } /** - * Load a dynamic library into the object. + * Load a dynamic library into the object. * If a dynamic library was already opened, it will be unload and replaced * - * @param path path to the dynamic library to load - * @param ext use DyLib::extension to specify the os extension (optional parameter) + * @param path the path of the dynamic library to load + * @param ext use dylib::extension to detect the current os extension (optional parameter) */ void open(const char *path) { close(); if (!path) - throw handle_error(getHandleError("(nullptr)")); - m_handle = openLib(path); + throw handle_error(get_handle_error("(nullptr)")); + m_handle = open_lib(path); if (!m_handle) - throw handle_error(getHandleError(path)); + throw handle_error(get_handle_error(path)); } void open(const std::string &path) @@ -220,9 +215,9 @@ class DyLib if (!ext) throw handle_error("bad extension : (nullptr)"); path += ext; - m_handle = openLib(path.c_str()); + m_handle = open_lib(path.c_str()); if (!m_handle) - throw handle_error(getHandleError(path)); + throw handle_error(get_handle_error(path)); } /** @@ -230,64 +225,64 @@ class DyLib * * @param T the template argument must be the function prototype. * it must be the same pattern as the template of std::function - * @param name symbol name of the function to get from the dynamic library + * @param name the symbol name of the function to get from the dynamic library * * @returns std::function that contains the function */ template - std::function getFunction(const char *name) const + std::function get_function(const char *name) const { if (!m_handle) throw handle_error("error : no dynamic library loaded"); if (!name) - throw symbol_error(getSymbolError("(nullptr)")); - auto sym = getSymbol(name); + throw symbol_error(get_symbol_error("(nullptr)")); + auto sym = get_symbol(name); if (!sym) - throw symbol_error(getSymbolError(name)); + throw symbol_error(get_symbol_error(name)); return reinterpret_cast(sym); } template - std::function getFunction(const std::string &name) const + std::function get_function(const std::string &name) const { - return getFunction(name.c_str()); + return get_function(name.c_str()); } /** * Get a global variable from the dynamic library currently loaded in the object * * @param T type of the global variable - * @param name name of the global variable to get from the dynamic library + * @param name the name of the global variable to get from the dynamic library * * @returns global variable of type */ template - T &getVariable(const char *name) const + T &get_variable(const char *name) const { if (!m_handle) throw handle_error("error : no dynamic library loaded"); if (!name) - throw symbol_error(getSymbolError("(nullptr)")); - auto sym = getSymbol(name); + throw symbol_error(get_symbol_error("(nullptr)")); + auto sym = get_symbol(name); if (!sym) - throw symbol_error(getSymbolError(name)); + throw symbol_error(get_symbol_error(name)); return *reinterpret_cast(sym); } template - T &getVariable(const std::string &name) const + T &get_variable(const std::string &name) const { - return getVariable(name.c_str()); + return get_variable(name.c_str()); } /** - * Close the dynamic library currently loaded in the object. + * Close the dynamic library currently loaded in the object. * This function will be automatically called by the class destructor */ void close() noexcept { if (m_handle) { - closeLib(); + close_lib(); m_handle = nullptr; } } diff --git a/cmake/FindGTest.cmake b/import/FetchGoogleTest.cmake similarity index 63% rename from cmake/FindGTest.cmake rename to import/FetchGoogleTest.cmake index 88c0655..4cd9fde 100644 --- a/cmake/FindGTest.cmake +++ b/import/FetchGoogleTest.cmake @@ -5,8 +5,8 @@ find_package(googletest QUIET) include(FetchContent) FetchContent_Declare( - googletest - URL https://github.com/google/googletest/archive/609281088cfefc76f9d0ce82e1ff6c30cc3591e5.zip + googletest + URL https://github.com/google/googletest/archive/609281088cfefc76f9d0ce82e1ff6c30cc3591e5.zip ) set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) diff --git a/test/myDynLib.cpp b/test/myDynLib.cpp index c0d54c1..87df4b4 100644 --- a/test/myDynLib.cpp +++ b/test/myDynLib.cpp @@ -1,16 +1,15 @@ #include +#include "dylib.hpp" -extern "C" { - double pi_value = 3.14159; - void *ptr = (void *)1; +DYLIB_API double pi_value = 3.14159; +DYLIB_API void *ptr = (void *)1; - double adder(double a, double b) - { - return a + b; - } +DYLIB_API double adder(double a, double b) +{ + return a + b; +} - void printHello() - { - std::cout << "Hello!" << std::endl; - } +DYLIB_API void print_hello() +{ + std::cout << "Hello!" << std::endl; } \ No newline at end of file diff --git a/test/tests.cpp b/test/tests.cpp index 2848b36..f9f2651 100644 --- a/test/tests.cpp +++ b/test/tests.cpp @@ -1,6 +1,6 @@ #include #include -#include "DyLib.hpp" +#include "dylib.hpp" class OSRedirector { private: @@ -32,22 +32,22 @@ TEST(exemple, exemple_test) OSRedirector oss(std::cout); try { - DyLib lib(std::string("./dynlib") + std::string(DyLib::extension)); + dylib lib(std::string("./dynlib") + std::string(dylib::extension)); - auto adder = lib.getFunction("adder"); + auto adder = lib.get_function("adder"); EXPECT_EQ(adder(5, 10), 15); - auto printer = lib.getFunction("printHello"); + auto printer = lib.get_function("print_hello"); printer(); EXPECT_EQ(oss.getContent(), "Hello!\n"); - double pi_value = lib.getVariable("pi_value"); + double pi_value = lib.get_variable("pi_value"); EXPECT_EQ(pi_value, 3.14159); - void *ptr = lib.getVariable("ptr"); + void *ptr = lib.get_variable("ptr"); EXPECT_EQ(ptr, (void *)1); } - catch (const DyLib::exception &) { + catch (const dylib::exception &) { EXPECT_EQ(true, false); } } @@ -55,10 +55,10 @@ TEST(exemple, exemple_test) TEST(ctor, bad_library) { try { - DyLib lib("./null.so"); + dylib lib("./null.so"); EXPECT_EQ(true, false); } - catch (const DyLib::exception &e) { + catch (const dylib::exception &e) { e.what(); EXPECT_EQ(true, true); } @@ -67,90 +67,90 @@ TEST(ctor, bad_library) TEST(dtor, mutiple_open_close) { try { - DyLib lib; + dylib lib; lib.close(); lib.close(); - lib.open(std::string("./dynlib") + std::string(DyLib::extension)); - lib.open(std::string("./dynlib") + std::string(DyLib::extension)); - EXPECT_EQ(lib.getFunction("adder")(1, 1), 2); + lib.open(std::string("./dynlib") + std::string(dylib::extension)); + lib.open(std::string("./dynlib") + std::string(dylib::extension)); + EXPECT_EQ(lib.get_function("adder")(1, 1), 2); lib.close(); lib.close(); lib.close(); - auto fn = lib.getFunction("adder"); + auto fn = lib.get_function("adder"); } - catch (const DyLib::exception &) { + catch (const dylib::exception &) { EXPECT_EQ(true, true); } } -TEST(getFunction, bad_handler) +TEST(get_function, bad_handler) { try { - DyLib lib(std::string("./dynlib") + std::string(DyLib::extension)); + dylib lib(std::string("./dynlib") + std::string(dylib::extension)); lib.close(); - auto adder = lib.getFunction("adder"); + auto adder = lib.get_function("adder"); EXPECT_EQ(true, false); } - catch (const DyLib::handle_error &) { + catch (const dylib::handle_error &) { EXPECT_EQ(true, true); } } -TEST(getFunction, bad_symbol) +TEST(get_function, bad_symbol) { try { - DyLib lib(std::string("./dynlib") + std::string(DyLib::extension)); - auto adder = lib.getFunction("unknow"); + dylib lib(std::string("./dynlib") + std::string(dylib::extension)); + auto adder = lib.get_function("unknown"); EXPECT_EQ(true, false); } - catch (const DyLib::symbol_error &) { + catch (const dylib::symbol_error &) { EXPECT_EQ(true, true); } } -TEST(getVariable, bad_handler) +TEST(get_variable, bad_handler) { try { - DyLib lib(std::string("./dynlib") + std::string(DyLib::extension)); + dylib lib(std::string("./dynlib") + std::string(dylib::extension)); lib.close(); - lib.getVariable("pi_value"); + lib.get_variable("pi_value"); EXPECT_EQ(true, false); } - catch (const DyLib::handle_error &) { + catch (const dylib::handle_error &) { EXPECT_EQ(true, true); } } -TEST(getVariable, bad_symbol) +TEST(get_variable, bad_symbol) { try { - DyLib lib(std::string("./dynlib") + std::string(DyLib::extension)); - lib.getVariable("unknow"); + dylib lib(std::string("./dynlib") + std::string(dylib::extension)); + lib.get_variable("unknown"); EXPECT_EQ(true, false); } - catch (const DyLib::symbol_error &) { + catch (const dylib::symbol_error &) { EXPECT_EQ(true, true); } } -TEST(getVariable, alter_variables) +TEST(get_variable, alter_variables) { try { - DyLib lib(std::string("./dynlib"), DyLib::extension); - DyLib other(std::move(lib)); - auto &pi = other.getVariable("pi_value"); + dylib lib(std::string("./dynlib"), dylib::extension); + dylib other(std::move(lib)); + auto &pi = other.get_variable("pi_value"); EXPECT_EQ(pi, 3.14159); pi = 123; - auto &pi1 = other.getVariable("pi_value"); + auto &pi1 = other.get_variable("pi_value"); EXPECT_EQ(pi1, 123); - auto &ptr = other.getVariable("ptr"); + auto &ptr = other.get_variable("ptr"); EXPECT_EQ(ptr, (void *)1); ptr = &lib; - auto &ptr1 = other.getVariable("ptr"); + auto &ptr1 = other.get_variable("ptr"); EXPECT_EQ(ptr1, &lib); } - catch (const DyLib::handle_error &) { + catch (const dylib::handle_error &) { EXPECT_EQ(true, false); } } @@ -158,26 +158,26 @@ TEST(getVariable, alter_variables) TEST(bad_arguments, null_pointer) { try { - DyLib lib(nullptr); + dylib lib(nullptr); EXPECT_EQ(true, false); } - catch (const DyLib::handle_error &) { + catch (const dylib::handle_error &) { EXPECT_EQ(true, true); } try { - DyLib lib(std::string("./dynlib") + std::string(DyLib::extension)); - auto nothing = lib.getFunction(nullptr); + dylib lib(std::string("./dynlib") + std::string(dylib::extension)); + auto nothing = lib.get_function(nullptr); EXPECT_EQ(true, false); } - catch (const DyLib::symbol_error &) { + catch (const dylib::symbol_error &) { EXPECT_EQ(true, true); } try { - DyLib lib(std::string("./dynlib") + std::string(DyLib::extension)); - lib.getVariable(nullptr); + dylib lib(std::string("./dynlib") + std::string(dylib::extension)); + lib.get_variable(nullptr); EXPECT_EQ(true, false); } - catch (const DyLib::symbol_error &) { + catch (const dylib::symbol_error &) { EXPECT_EQ(true, true); } } @@ -185,17 +185,17 @@ TEST(bad_arguments, null_pointer) TEST(bad_arguments, handle_and_ext) { try { - DyLib lib("./badlib", DyLib::extension); + dylib lib("./badlib", dylib::extension); EXPECT_EQ(true, false); } - catch (const DyLib::handle_error &) { + catch (const dylib::handle_error &) { EXPECT_EQ(true, true); } try { - DyLib lib(std::string("./dynlib"), nullptr); + dylib lib(std::string("./dynlib"), nullptr); EXPECT_EQ(true, false); } - catch (const DyLib::handle_error &) { + catch (const dylib::handle_error &) { EXPECT_EQ(true, true); } } @@ -203,11 +203,11 @@ TEST(bad_arguments, handle_and_ext) TEST(os_detector, basic_test) { try { - DyLib lib(std::string("./dynlib"), DyLib::extension); - auto pi = lib.getVariable("pi_value"); + dylib lib(std::string("./dynlib"), dylib::extension); + auto pi = lib.get_variable("pi_value"); EXPECT_EQ(pi, 3.14159); } - catch (const DyLib::exception &) { + catch (const dylib::exception &) { EXPECT_EQ(true, false); } } @@ -215,17 +215,17 @@ TEST(os_detector, basic_test) TEST(std_move, basic_test) { try { - DyLib lib(std::string("./dynlib"), DyLib::extension); - DyLib other(std::move(lib)); - auto pi = other.getVariable("pi_value"); + dylib lib(std::string("./dynlib"), dylib::extension); + dylib other(std::move(lib)); + auto pi = other.get_variable("pi_value"); EXPECT_EQ(pi, 3.14159); lib = std::move(other); - auto ptr = lib.getVariable("ptr"); + auto ptr = lib.get_variable("ptr"); EXPECT_EQ(ptr, (void *)1); - other.getVariable("pi_value"); + other.get_variable("pi_value"); EXPECT_EQ(true, false); } - catch (const DyLib::handle_error &) { + catch (const dylib::handle_error &) { EXPECT_EQ(true, true); } }