diff --git a/CMakeLists.txt b/CMakeLists.txt index b9451b6..977d38a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ -project(ISO_object LANGUAGES C CXX) cmake_minimum_required(VERSION 3.14) +project(ISO_object LANGUAGES C CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) @@ -8,7 +8,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) # RPATH/RUNPATH tells a binary where to look for libraries at runtime # It is useful e.g. when multiple copies of the same shared library exist in various paths (such as LD_LIBRARY_PATH, /usr/local/lib, etc..). # However, RPATH has higher priority than LD_LIBRARY_PATH, while RUNPATH has lower priority -set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--disable-new-dtags") +#set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--disable-new-dtags") #throws error? # Build flags @@ -45,15 +45,25 @@ SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) include(GNUInstallDirs) -if (BUILDING_FOR_ANDROID) # Boost is found in variables set by android toolchain upstream - add_library(boost_system SHARED IMPORTED) - set_target_properties(boost_system PROPERTIES IMPORTED_LOCATION - ${ANDROID_BOOST_LIB_DIR}/libboost_system.so) - include_directories(${ANDROID_BOOST_INCLUDE_DIR}) -else() # Find boost normally - find_package(Boost REQUIRED COMPONENTS system) + + +find_package(Boost 1.83.0 REQUIRED) +include_directories(${Boost_INCLUDE_DIRS}) +if(Boost_FOUND) + set(BOOST_INCLUDE_DIR "${Boost_ROOT}") + set(Boost_DEBUG ON) + set(Boost_USE_STATIC_LIBS OFF) #Set to on + message(STATUS "Boost found: ${Boost_VERSION}") + message(STATUS "Boost include dirs: ${Boost_INCLUDE_DIRS}") + message(STATUS "Boost libraries: ${Boost_LIBRARIES}") +else() + message(FATAL_ERROR "Boost not found") endif() +# add_definitions(-DBOOST_ALL_NO_LIB) +# add_subdirectory(${Boost_INSTALL_DIR}/boost) +set(Boost_USE_STATIC_ ON) + # Library target add_library(${ISOOBJECT_LIBRARY} SHARED @@ -61,25 +71,24 @@ add_library(${ISOOBJECT_LIBRARY} SHARED ${CMAKE_CURRENT_SOURCE_DIR}/src/iso22133state.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/trajDecoder.cpp ) +target_compile_definitions(${ISOOBJECT_LIBRARY} PRIVATE ISO_OBJECT_EXPORTS) target_include_directories(${ISOOBJECT_LIBRARY} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/inc ${CMAKE_CURRENT_SOURCE_DIR}/sigslot/include/sigslot ${CMAKE_CURRENT_SOURCE_DIR}/iso22133 + ${Boost_INCLUDE_DIRS} ) set(ISO_OBJ_LIBS - ${ISO22133_LIBRARY} atomic pthread Boost::system) -set(ISO_OBJ_LIBS_ANDROID - ${ISO22133_LIBRARY} atomic ${boost_system}) -if (BUILDING_FOR_ANDROID) - target_link_libraries(${ISOOBJECT_LIBRARY} - ${ISO_OBJ_LIBS_ANDROID} - ) -else() - target_link_libraries(${ISOOBJECT_LIBRARY} - ${ISO_OBJ_LIBS} + ${ISO22133_LIBRARY})# Boost::system) + +target_link_libraries(${ISOOBJECT_LIBRARY} + ${ISO_OBJ_LIBS} + ${Boost_LIBRARIES} ) -endif() + + +set(CMAKE_VERBOSE_MAKEFILE ON) set_property(TARGET ${ISOOBJECT_LIBRARY} PROPERTY PUBLIC_HEADER ${CMAKE_CURRENT_SOURCE_DIR}/inc/iso22133object.hpp @@ -109,23 +118,6 @@ set_property(TARGET ${ISOOBJECT_LIBRARY} APPEND PROPERTY PUBLIC_HEADER ${CMAKE_CURRENT_SOURCE_DIR}/inc/udpServer.hpp ) -if (NOT WITH_SWIG AND NOT BUILDING_FOR_ANDROID) -find_package(Boost REQUIRED COMPONENTS program_options) - -# Demo target, only build if not swigging -add_executable(${ISOOBJECT_TEST} demoIsoObject.cpp) - -target_include_directories(${ISOOBJECT_TEST} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/inc -) - -target_link_libraries(${ISOOBJECT_TEST} LINK_PUBLIC - ${ISOOBJECT_LIBRARY} - Boost::program_options -) - -endif() - install(CODE "MESSAGE(STATUS \"Installing target ${ISOOBJECT_LIBRARY}\")") install(TARGETS ${ISOOBJECT_LIBRARY} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} @@ -133,85 +125,3 @@ install(TARGETS ${ISOOBJECT_LIBRARY} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) - -# SWIG -if (WITH_SWIG) - find_package(SWIG REQUIRED) - if(NOT SWIG_FOUND) - message(WARNING "SWIG not found") - else() - #Policy for swig_add_library to put target inside first argument to the function - cmake_policy(SET CMP0078 NEW) - #Policy for passing SWIG_MODULE_NAME to swig compiler as -module - cmake_policy(SET CMP0086 NEW) - - include(${SWIG_USE_FILE}) - - if(SWIG_WITH_JAVA) - if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Android") - find_package(JNI REQUIRED) - endif() - SET(CMAKE_SWIG_FLAGS -package org.asta.isoObject) - elseif(SWIG_WITH_PYTHON) - find_package(Python COMPONENTS Development) - SET(CMAKE_SWIG_FLAGS "-threads") - endif() - - set(ISO22133_SWIGGED isoObject_wrap) - - set_property(SOURCE isoObject.i PROPERTY CPLUSPLUS ON) - set_property(SOURCE isoObject.i PROPERTY INCLUDE_DIRECTORIES - ${CMAKE_CURRENT_SOURCE_DIR}/inc - ${CMAKE_CURRENT_SOURCE_DIR}/sigslot/include/sigslot - ${CMAKE_CURRENT_SOURCE_DIR}/iso22133 - ${Python_INCLUDE_DIRS} #Note that cmake ignored empty variables - ${JNI_INCLUDE_DIRS} - ${Boost_INCLUDE_DIRS} - ) - swig_add_library(${ISO22133_SWIGGED} - TYPE SHARED - LANGUAGE ${SWIG_TARGET_LANG} - SOURCES isoObject.i - ) - set_property(TARGET ${ISO22133_SWIGGED} PROPERTY USE_TARGET_INCLUDE_DIRECTORIES TRUE) - target_include_directories(${ISO22133_SWIGGED} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/inc - ${CMAKE_CURRENT_SOURCE_DIR}/sigslot/include/sigslot - ${CMAKE_CURRENT_SOURCE_DIR}/iso22133 - ${Python_INCLUDE_DIRS} - ${JNI_INCLUDE_DIRS} - ) - - target_link_libraries(${ISO22133_SWIGGED} - ${ISOOBJECT_LIBRARY} - ${ISO22133_LIBRARY} - atomic - ${Python_LIBRARIES} - ${JNI_LIBRARIES} - ) - - if(SWIG_WITH_PYTHON) - execute_process(COMMAND python3 -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())" OUTPUT_VARIABLE PYTHON_SITE_PACKAGES OUTPUT_STRIP_TRAILING_WHITESPACE) - install(TARGETS ${ISO22133_SWIGGED} DESTINATION ${PYTHON_SITE_PACKAGES}) - install(FILES ${CMAKE_BINARY_DIR}/isoObject_wrap.py DESTINATION ${PYTHON_SITE_PACKAGES}) - endif() - endif() -endif() - -# Build tests -if (BUILD_TESTING) - enable_testing() - file(GLOB TEST_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/tests/*.cpp) - add_executable(${ISOOBJECT_LIBRARY}_test - ${TEST_SOURCES} - ) - target_link_libraries(${ISOOBJECT_LIBRARY}_test - gtest_main - ${ISOOBJECT_LIBRARY} - ) - target_include_directories(${ISOOBJECT_LIBRARY}_test PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/inc - ) - include(GoogleTest) - gtest_discover_tests(${ISOOBJECT_LIBRARY}_test) -endif() \ No newline at end of file diff --git a/inc/iso22133object.hpp b/inc/iso22133object.hpp index d30f6be..172da3c 100644 --- a/inc/iso22133object.hpp +++ b/inc/iso22133object.hpp @@ -1,18 +1,31 @@ #pragma once +#ifdef ISO_OBJECT_EXPORTS +#define ISO22133OBJECT_API __declspec(dllexport) +#else +#define ISO22133OBJECT_API __declspec(dllimport) +#endif + #include #include #include #include #include +#include #include "header.h" #include "iso22133.h" #include "iso22133state.hpp" #include "trajDecoder.hpp" #include "signal.hpp" -#include "tcpServer.hpp" -#include "udpServer.hpp" +#ifndef __INTELLISENSE__ + #include "tcpServer.hpp" + #include "udpServer.hpp" +#endif +#ifdef __INTELLISENSE__ // Workaround for intellisense bug with boost for VS2017 + #include "tcpServer_temp.hpp" + #include "udpServer_temp.hpp" +#endif namespace ISO22133 { class State; @@ -36,7 +49,7 @@ class PreRunning; * the inheriting class must implement the pure * virtual functions. */ -class TestObject { +class ISO22133OBJECT_API TestObject { friend class State; friend class Unknown; friend class Off; @@ -97,6 +110,27 @@ class TestObject { void startHEABCheck() { heabTimeoutThread = std::thread(&TestObject::checkHeabLoop, this); } void startSendMonr() { monrThread = std::thread(&TestObject::sendMonrLoop, this); } + void abortRunning() + { + + try { + state->handleEvent(*this, ISO22133::Events::W); + } + catch(const std::runtime_error& e) { + std::cerr << e.what() << '\n'; + } + } + + void confirmArming() + { + try { + state->handleEvent(*this, ISO22133::Events::N); + } + catch(const std::runtime_error& e) { + std::cerr << e.what() << '\n'; + } + } + protected: //! Wrapper for handling function that converts to char vector int handleMessage(char *buffer, int bufferLen); @@ -248,7 +282,7 @@ class TestObject { namespace std::chrono { template -struct timeval to_timeval(Duration&& d) { +timeval to_timeval(Duration&& d) { std::chrono::seconds const sec = std::chrono::duration_cast(d); struct timeval tv; tv.tv_sec = sec.count(); diff --git a/inc/iso22133state.hpp b/inc/iso22133state.hpp index 61be2ea..247e612 100644 --- a/inc/iso22133state.hpp +++ b/inc/iso22133state.hpp @@ -1,11 +1,18 @@ #pragma once +#ifdef ISO_OBJECT_EXPORTS +#define ISO22133STATE_API __declspec(dllexport) +#define ISO22133DISARMED_API __declspec(dllexport) +#else +#define ISO22133STATE_API __declspec(dllimport) +#define ISO22133DISARMED_API __declspec(dllimport) +#endif + #include #include #include #include #include -#include extern "C"{ #include "iso22133.h" #include "header.h" @@ -91,7 +98,7 @@ static const std::map stateNames = { * ISO 22133. It is not intended to be used outside of * iso22133object.h */ -class State { +class ISO22133STATE_API State { friend class TestObject; public: State() {} @@ -163,7 +170,7 @@ class Armed : public State { virtual ObjectStateID getStateID() const final override { return ISO_OBJECT_STATE_ARMED; } }; -class Disarmed : public State { +class ISO22133DISARMED_API Disarmed : public State { public: virtual ObjectStateID getStateID() const final override { return ISO_OBJECT_STATE_DISARMED; } virtual void onEnter(TestObject& obj); diff --git a/inc/tcpServer.hpp b/inc/tcpServer.hpp index b8db4d2..591c93a 100644 --- a/inc/tcpServer.hpp +++ b/inc/tcpServer.hpp @@ -1,5 +1,5 @@ #pragma once - +#include // Workaround for include issue caused by some boost lib? #include #include #include diff --git a/inc/tcpServer_temp.hpp b/inc/tcpServer_temp.hpp new file mode 100644 index 0000000..fac7263 --- /dev/null +++ b/inc/tcpServer_temp.hpp @@ -0,0 +1,4 @@ +#pragma once + +class TcpServer { +}; diff --git a/inc/trajDecoder.hpp b/inc/trajDecoder.hpp index fa5b666..4c2fde9 100644 --- a/inc/trajDecoder.hpp +++ b/inc/trajDecoder.hpp @@ -5,8 +5,8 @@ #include #include -#include "iso22133.h" #include "traj.h" +#include "iso22133.h" /** * @brief Class for decoding TRAJ messages. Stores TRAJ data and @@ -16,7 +16,7 @@ class TrajDecoder { public: TrajDecoder(bool debug) : debug(debug), expectingTRAJPoints(false) {}; TrajDecoder() : debug(false), expectingTRAJPoints(false) {}; - ssize_t DecodeTRAJ(std::vector&, bool debug = false); + size_t DecodeTRAJ(std::vector&, bool debug = false); bool ExpectingTrajPoints() const { return this->expectingTRAJPoints; } TrajectoryHeaderType getTrajHeader() const; std::vector getTraj() const; diff --git a/inc/udpServer_temp.hpp b/inc/udpServer_temp.hpp new file mode 100644 index 0000000..25034b5 --- /dev/null +++ b/inc/udpServer_temp.hpp @@ -0,0 +1,4 @@ +#pragma once + +class UdpServer { +}; diff --git a/isoObject.i b/isoObject.i index 41ee81a..f4e2590 100644 --- a/isoObject.i +++ b/isoObject.i @@ -19,7 +19,7 @@ %rename(LessThan) operator<(const Transition &lhs, const Transition &rhs); %typemap(in) (char *buffer, int bufferLen) { - Py_ssize_t len; + Py_size_t len; PyBytes_AsStringAndSize($input, &$1, &len); $2 = (int)len; } @@ -50,7 +50,7 @@ namespace std { }; typedef double double_t; -typedef long int ssize_t; +typedef long int size_t; struct timeval { long int tv_sec; diff --git a/src/iso22133object.cpp b/src/iso22133object.cpp index 5a62441..955edb8 100644 --- a/src/iso22133object.cpp +++ b/src/iso22133object.cpp @@ -243,7 +243,7 @@ void TestObject::receiveUDP() { void TestObject::checkHeabTimeout() { using namespace std::chrono; - std::scoped_lock lock(heabMutex); + std::unique_lock lock(heabMutex); // Check time difference of received HEAB and last HEAB auto timeSinceHeab = steady_clock::now() - lastHeabTime; if (!awaitingFirstHeab && timeSinceHeab > heartbeatTimeout) { @@ -260,6 +260,7 @@ void TestObject::checkHeabLoop() { auto t = std::chrono::steady_clock::now(); checkHeabTimeout(); // Don't lock the mutex all the time + std::this_thread::sleep_until(t + expectedHeartbeatPeriod); } } @@ -405,7 +406,7 @@ void TestObject::handleHEAB(HeabMessageDataType& heab) { std::cerr << ss.str(); // TODO: do something } - std::scoped_lock lock(heabMutex); + std::unique_lock lock(heabMutex); lastHeabTime = steady_clock::now(); awaitingFirstHeab = false; @@ -427,7 +428,7 @@ void TestObject::handleHEAB(HeabMessageDataType& heab) { } std::chrono::milliseconds TestObject::getNetworkDelay() { - std::scoped_lock lock(netwrkDelayMutex); + std::unique_lock lock(netwrkDelayMutex); if (awaitingFirstHeab) { return std::chrono::milliseconds(0); } @@ -435,7 +436,7 @@ std::chrono::milliseconds TestObject::getNetworkDelay() { } void TestObject::setNetworkDelay(std::chrono::milliseconds delay) { - std::scoped_lock lock(netwrkDelayMutex); + std::unique_lock lock(netwrkDelayMutex); estimatedNetworkDelay = delay; } diff --git a/src/iso22133state.cpp b/src/iso22133state.cpp index e2a6b56..3cd8118 100644 --- a/src/iso22133state.cpp +++ b/src/iso22133state.cpp @@ -10,7 +10,7 @@ * @param event Event according to ISO22133::EventType */ void ISO22133::State::handleEvent(TestObject& obj, const ISO22133::Events::EventType event) { - std::scoped_lock lock(eventMutex); + std::unique_lock lock(eventMutex); auto transition = std::find_if(language.begin(), language.end(), [&event, this](const ISO22133::Transition& tr) { return event == tr.event && this->getStateID() == tr.source; @@ -64,6 +64,7 @@ void ISO22133::State::handleEvent(TestObject& obj, const ISO22133::Events::Event obj.state = obj.createUnknown(); break; } + lock.unlock(); delete temp; std::cout << "Entering state: " << obj.state->getName() << std::endl; @@ -115,7 +116,7 @@ void ISO22133::State::handleOSEM(TestObject& obj, ObjectSettingsType& osem) { msg << "Got OSEM - set transmitter ID to " << obj.transmitterID << std::endl; std::cout << msg.str(); - obj.expectedHeartbeatPeriod = std::chrono::milliseconds(1000 / (uint)osem.rate.heab); + obj.expectedHeartbeatPeriod = std::chrono::milliseconds(1000 / (u_int)osem.rate.heab); msg.str(std::string()); msg << "Setting HEAB period to " << obj.expectedHeartbeatPeriod.count() << " ms. (" << 1000 / obj.expectedHeartbeatPeriod.count() << " Hz) " << std::endl; @@ -127,7 +128,7 @@ void ISO22133::State::handleOSEM(TestObject& obj, ObjectSettingsType& osem) { << 1000 / obj.heartbeatTimeout.count() << " Hz) " << std::endl; std::cout << msg.str(); - obj.monrPeriod = std::chrono::milliseconds(1000 / (uint)osem.rate.monr); + obj.monrPeriod = std::chrono::milliseconds(1000 / (u_int)osem.rate.monr); msg.str(std::string()); msg << "Setting MONR period to " << obj.monrPeriod.count() << " ms. (" << 1000 / obj.monrPeriod.count() << " Hz) " << std::endl; @@ -162,7 +163,7 @@ void ISO22133::State::handleSTRT(TestObject& obj, StartMessageType& strt) { ); struct timeval diff; - timersub(&strt.startTime, ¤tTime, &diff); + timersub_w(&strt.startTime, ¤tTime, &diff); uint32_t diffmySec = diff.tv_sec*1e6 + diff.tv_usec; int diffint = diff.tv_sec*1e6 + diff.tv_usec; diff --git a/src/trajDecoder.cpp b/src/trajDecoder.cpp index 2d519b2..282944f 100644 --- a/src/trajDecoder.cpp +++ b/src/trajDecoder.cpp @@ -4,7 +4,7 @@ #include "trajDecoder.hpp" #include "iso22133.h" -ssize_t TrajDecoder::DecodeTRAJ(std::vector& dataBuffer, bool debug) { +size_t TrajDecoder::DecodeTRAJ(std::vector& dataBuffer, bool debug) { std::lock_guard lock(this->guard); copiedData = dataBuffer; int tmpByteCounter;