From 02206c82e36d41a9cdbcf23de3fa158efd712405 Mon Sep 17 00:00:00 2001 From: Christian von Arnim Date: Tue, 30 May 2023 08:53:45 +0200 Subject: [PATCH 1/2] cmake: Install library and AdsTool Use the library like so: find_package(Threads REQUIRED) find_package(ads REQUIRED) add_executable(myAdsApp myAdsApp.cpp) target_link_libraries(myAdsApp ads::ads) --- AdsLib/CMakeLists.txt | 9 +++++++- AdsTool/CMakeLists.txt | 2 ++ CMakeLists.txt | 49 ++++++++++++++++++++++++++++++++++++++++++ cmake/Config.cmake.in | 3 +++ 4 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 AdsTool/CMakeLists.txt create mode 100644 cmake/Config.cmake.in diff --git a/AdsLib/CMakeLists.txt b/AdsLib/CMakeLists.txt index 47f97a4f..be174070 100644 --- a/AdsLib/CMakeLists.txt +++ b/AdsLib/CMakeLists.txt @@ -10,6 +10,11 @@ set(SOURCES RTimeAccess.cpp Sockets.cpp + RegistryAccess.cpp + SymbolAccess.cpp + + bhf/ParameterList.cpp + standalone/AdsLib.cpp standalone/AmsConnection.cpp standalone/AmsNetId.cpp @@ -19,8 +24,10 @@ set(SOURCES ) add_library(ads ${SOURCES}) +add_library(ads::ads ALIAS ads) -target_include_directories(ads PUBLIC .) +target_include_directories(ads PUBLIC $ +$) if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") target_link_libraries(ads PUBLIC wsock32) diff --git a/AdsTool/CMakeLists.txt b/AdsTool/CMakeLists.txt new file mode 100644 index 00000000..7d4cad58 --- /dev/null +++ b/AdsTool/CMakeLists.txt @@ -0,0 +1,2 @@ +add_executable(AdsTool main.cpp) +target_link_libraries(AdsTool PUBLIC ads::ads) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2de5ab81..e907e8f3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,5 +23,54 @@ add_definitions(-DCONFIG_DEFAULT_LOGLEVEL=1) option(BUILD_SHARED_LIBS "Build using shared libraries" ON) add_subdirectory(AdsLib) +add_subdirectory(AdsTool) add_subdirectory(AdsLibTest) add_subdirectory(example) + + +# Install library +include(GenerateExportHeader) +set(ADSLIB_VERSION 0.0.20) + +set_property(TARGET ads PROPERTY VERSION ${ADSLIB_VERSION}) +set_property(TARGET ads PROPERTY SOVERSION 3) + + +# export library (either static or shared depending on BUILD_SHARED_LIBS) +install(TARGETS ads AdsTool + EXPORT adsTargets + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib + RUNTIME DESTINATION bin + INCLUDES DESTINATION include + ) + +install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/AdsLib/ DESTINATION include/ads/ + FILES_MATCHING PATTERN "*.hpp" PATTERN "*.h") + + +set(cmake_configfile_install lib/cmake/ads) +set(target_install_dest_name "${cmake_configfile_install}/adsTargets.cmake") + +include(CMakePackageConfigHelpers) +write_basic_package_version_file( + "${CMAKE_CURRENT_BINARY_DIR}/adsConfigVersion.cmake" + VERSION ${ADSLIB_VERSION} + COMPATIBILITY AnyNewerVersion +) + +configure_package_config_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/Config.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/cmake/adsConfig.cmake" + INSTALL_DESTINATION "${cmake_configfile_install}" + PATH_VARS target_install_dest_name) + +install(EXPORT adsTargets + FILE adsTargets.cmake + NAMESPACE ads:: + DESTINATION "${cmake_configfile_install}" + EXPORT_LINK_INTERFACE_LIBRARIES) + +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/cmake/adsConfig.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/adsConfigVersion.cmake" + DESTINATION "${cmake_configfile_install}") + diff --git a/cmake/Config.cmake.in b/cmake/Config.cmake.in new file mode 100644 index 00000000..d9ff2d3d --- /dev/null +++ b/cmake/Config.cmake.in @@ -0,0 +1,3 @@ +@PACKAGE_INIT@ + +include ("@PACKAGE_target_install_dest_name@") From 2f6d290fdadb153e6511463d4db40ffefbc9b275 Mon Sep 17 00:00:00 2001 From: Christian von Arnim Date: Tue, 13 Jun 2023 16:43:38 +0200 Subject: [PATCH 2/2] AdsLib: Allow std::function for notifications --- AdsLib/AdsDevice.cpp | 46 +++++++++++++++++++++++++++++++++---- AdsLib/AdsDevice.h | 16 ++++++++++--- AdsLib/AdsNotificationOOI.h | 35 ++++++++++++++++++++++++---- 3 files changed, 85 insertions(+), 12 deletions(-) diff --git a/AdsLib/AdsDevice.cpp b/AdsLib/AdsDevice.cpp index 1eb91cb7..f565c711 100644 --- a/AdsLib/AdsDevice.cpp +++ b/AdsLib/AdsDevice.cpp @@ -7,6 +7,11 @@ #include "AdsException.h" #include "AdsLib.h" #include +#include "Log.h" + +std::mutex AdsDevice::m_CallbackMutex; +uint32_t AdsDevice::m_NextCallbackHandle = 0x80000000; +std::unordered_map AdsDevice::m_FuncCallbacks; static AmsNetId* AddRoute(AmsNetId ams, const char* ip) { @@ -23,8 +28,9 @@ AdsDevice::AdsDevice(const std::string& ipV4, AmsNetId netId, uint16_t port) m_LocalPort(new long { AdsPortOpenEx() }, {AdsPortCloseEx}) {} -long AdsDevice::DeleteNotificationHandle(uint32_t handle) const +long AdsDevice::DeleteNotificationHandle(uint32_t handle, uint32_t hUser) const { + AdsDevice::DeleteFuncCallback(hUser); if (handle) { return AdsSyncDelDeviceNotificationReqEx(GetLocalPort(), &m_Addr, handle); } @@ -41,6 +47,7 @@ long AdsDevice::DeleteSymbolHandle(uint32_t handle) const return WriteReqEx(ADSIGRP_SYM_RELEASEHND, 0, sizeof(handle), &handle); } + DeviceInfo AdsDevice::GetDeviceInfo() const { DeviceInfo info; @@ -83,22 +90,23 @@ AdsHandle AdsDevice::GetHandle(const std::string& symbolName) const AdsHandle AdsDevice::GetHandle(const uint32_t indexGroup, const uint32_t indexOffset, const AdsNotificationAttrib& notificationAttributes, - PAdsNotificationFuncEx callback, - const uint32_t hUser) const + PAdsNotificationFuncExFunc callback) const { uint32_t handle = 0; + uint32_t hUser = AdsDevice::AddFuncCallback(callback); auto error = AdsSyncAddDeviceNotificationReqEx( *m_LocalPort, &m_Addr, indexGroup, indexOffset, ¬ificationAttributes, - callback, + &AdsDevice::CallFuncCallback, hUser, &handle); if (error || !handle) { + AdsDevice::DeleteFuncCallback(hUser); throw AdsException(error); } handle = bhf::ads::letoh(handle); - return {new uint32_t {handle}, {std::bind(&AdsDevice::DeleteNotificationHandle, this, std::placeholders::_1)}}; + return {new uint32_t {handle}, {std::bind(&AdsDevice::DeleteNotificationHandle, this, std::placeholders::_1, hUser)}}; } long AdsDevice::GetLocalPort() const @@ -214,3 +222,31 @@ long AdsDevice::WriteReqEx(uint32_t group, uint32_t offset, size_t length, const } return AdsSyncWriteReqEx(GetLocalPort(), &m_Addr, group, offset, static_cast(length), buffer); } + +uint32_t AdsDevice::AddFuncCallback(PAdsNotificationFuncExFunc callback) +{ + std::lock_guard lock(m_CallbackMutex); + m_FuncCallbacks.insert(std::make_pair(m_NextCallbackHandle, callback)); + return m_NextCallbackHandle++; +} + +void AdsDevice::DeleteFuncCallback(uint32_t handle) +{ + std::lock_guard lock(m_CallbackMutex); + if(m_FuncCallbacks.erase(handle) == 0) + { + LOG_WARN("Handle " << handle << " has already been deleted."); + } +} + +void AdsDevice::CallFuncCallback(CONST AmsAddr* pAddr, const AdsNotificationHeader* pNotification, uint32_t hUser) +{ + std::lock_guard lock(m_CallbackMutex); + auto it = m_FuncCallbacks.find(hUser); + if(it == m_FuncCallbacks.end()) + { + LOG_WARN("Callback for handle " << hUser << " not found."); + return; + } + it->second(pAddr, pNotification); +} diff --git a/AdsLib/AdsDevice.h b/AdsLib/AdsDevice.h index ca1c77c3..07d25674 100644 --- a/AdsLib/AdsDevice.h +++ b/AdsLib/AdsDevice.h @@ -11,6 +11,8 @@ #include #include #include +#include +#include /** * @brief Maximum size for device name. @@ -52,6 +54,8 @@ using AdsResource = std::unique_ptr >; using AdsHandle = AdsResource; +typedef std::function PAdsNotificationFuncExFunc; + struct AdsDevice { AdsDevice(const std::string& ipV4, AmsNetId netId, uint16_t port); @@ -67,8 +71,7 @@ struct AdsDevice { AdsHandle GetHandle(uint32_t indexGroup, uint32_t indexOffset, const AdsNotificationAttrib& notificationAttributes, - PAdsNotificationFuncEx callback, - uint32_t hUser) const; + PAdsNotificationFuncExFunc callback) const; /** Get handle to access files */ AdsHandle OpenFile(const std::string& filename, uint32_t flags) const; @@ -96,6 +99,13 @@ struct AdsDevice { private: AdsResource m_LocalPort; long CloseFile(uint32_t handle) const; - long DeleteNotificationHandle(uint32_t handle) const; + long DeleteNotificationHandle(uint32_t handle, uint32_t hUser) const; long DeleteSymbolHandle(uint32_t handle) const; + + static std::mutex m_CallbackMutex; + static uint32_t m_NextCallbackHandle; + static std::unordered_map m_FuncCallbacks; + static uint32_t AddFuncCallback(PAdsNotificationFuncExFunc callback); + static void DeleteFuncCallback(uint32_t handle); + static void CallFuncCallback(const AmsAddr* pAddr, const AdsNotificationHeader* pNotification, uint32_t hUser); }; diff --git a/AdsLib/AdsNotificationOOI.h b/AdsLib/AdsNotificationOOI.h index 2487b9cb..12d5128a 100644 --- a/AdsLib/AdsNotificationOOI.h +++ b/AdsLib/AdsNotificationOOI.h @@ -19,7 +19,18 @@ struct AdsNotification { uint32_t hUser) : m_Symbol(route.GetHandle(symbolName)), m_Notification(route.GetHandle(ADSIGRP_SYM_VALBYHND, *m_Symbol, notificationAttributes, - reinterpret_cast(callback), hUser)) + [hUser, callback](const AmsAddr* pAddr, const AdsNotificationHeader* pNotification){ + callback(pAddr, pNotification, hUser); + })) + {} + + AdsNotification(const AdsDevice& route, + const std::string& symbolName, + const AdsNotificationAttrib& notificationAttributes, + PAdsNotificationFuncExFunc callback) + : m_Symbol(route.GetHandle(symbolName)), + m_Notification(route.GetHandle(ADSIGRP_SYM_VALBYHND, *m_Symbol, notificationAttributes, + callback)) {} AdsNotification(const AdsDevice& route, @@ -29,7 +40,9 @@ struct AdsNotification { uint32_t hUser) : m_Symbol(route.GetHandle(symbolName)), m_Notification(route.GetHandle(ADSIGRP_SYM_VALBYHND, *m_Symbol, notificationAttributes, - reinterpret_cast(callback), hUser)) + [hUser, callback](const AmsAddr* pAddr, const AdsNotificationHeader* pNotification){ + callback(const_cast(pAddr), const_cast(pNotification), hUser); + })) {} AdsNotification(const AdsDevice& route, @@ -40,7 +53,19 @@ struct AdsNotification { uint32_t hUser) : m_Symbol{route.GetHandle(indexOffset)}, m_Notification(route.GetHandle(indexGroup, indexOffset, notificationAttributes, - reinterpret_cast(callback), hUser)) + [hUser, callback](const AmsAddr* pAddr, const AdsNotificationHeader* pNotification){ + callback(pAddr, pNotification, hUser); + })) + {} + + AdsNotification(const AdsDevice& route, + uint32_t indexGroup, + uint32_t indexOffset, + const AdsNotificationAttrib& notificationAttributes, + PAdsNotificationFuncExFunc callback) + : m_Symbol{route.GetHandle(indexOffset)}, + m_Notification(route.GetHandle(indexGroup, indexOffset, notificationAttributes, + callback)) {} AdsNotification(const AdsDevice& route, @@ -51,7 +76,9 @@ struct AdsNotification { uint32_t hUser) : m_Symbol{route.GetHandle(indexOffset)}, m_Notification(route.GetHandle(indexGroup, indexOffset, notificationAttributes, - reinterpret_cast(callback), hUser)) + [hUser, callback](const AmsAddr* pAddr, const AdsNotificationHeader* pNotification){ + callback(const_cast(pAddr), const_cast(pNotification), hUser); + })) {} private: