添加win32支持,重构XNCore模块结构

This commit is contained in:
zd383321154 2025-06-11 23:27:16 +08:00
parent 069ea0ea37
commit e6392c5228
85 changed files with 1562 additions and 1191 deletions

1
.gitignore vendored
View File

@ -39,3 +39,4 @@ build/
log/
logs/
Packages/
ThirdPart/

View File

@ -81,6 +81,27 @@
"unordered_set": "cpp",
"fstream": "cpp",
"forward_list": "cpp",
"valarray": "cpp"
"valarray": "cpp",
"filesystem": "cpp",
"charconv": "cpp",
"format": "cpp",
"ios": "cpp",
"locale": "cpp",
"queue": "cpp",
"xfacet": "cpp",
"xhash": "cpp",
"xiosbase": "cpp",
"xlocale": "cpp",
"xlocbuf": "cpp",
"xlocinfo": "cpp",
"xlocmes": "cpp",
"xlocmon": "cpp",
"xlocnum": "cpp",
"xloctime": "cpp",
"xmemory": "cpp",
"xstring": "cpp",
"xtr1common": "cpp",
"xtree": "cpp",
"xutility": "cpp"
}
}

View File

@ -2,86 +2,130 @@ cmake_minimum_required(VERSION 3.16)
project(XNCore LANGUAGES CXX)
#
set(THIRD_PARTY_DIR "I:/MyPrj/XNSim/ThirdPart")
# Windows32
if(WIN32)
set(CMAKE_GENERATOR_PLATFORM "Win32" CACHE STRING "Target platform" FORCE)
set(CMAKE_VS_PLATFORM_NAME "Win32" CACHE STRING "Win32/x64 build." FORCE)
set_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB32_PATHS TRUE)
set_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS FALSE)
set(CMAKE_SIZEOF_VOID_P 4)
add_definitions(-DWIN32 -D_WINDOWS)
endif()
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
if(WIN32)
# OpenSSL使
set(OPENSSL_ROOT_DIR "${THIRD_PARTY_DIR}/openssl" CACHE PATH "OpenSSL root directory")
set(OPENSSL_INCLUDE_DIR "${OPENSSL_ROOT_DIR}/include" CACHE PATH "OpenSSL include directory")
set(OPENSSL_LIBRARIES "${OPENSSL_ROOT_DIR}/lib" CACHE PATH "OpenSSL library directory")
set(OPENSSL_CRYPTO_LIBRARY "${OPENSSL_ROOT_DIR}/lib/libcrypto.lib" CACHE FILEPATH "OpenSSL crypto library")
set(OPENSSL_SSL_LIBRARY "${OPENSSL_ROOT_DIR}/lib/libssl.lib" CACHE FILEPATH "OpenSSL ssl library")
# OpenSSL
if(NOT EXISTS "${OPENSSL_INCLUDE_DIR}/openssl/ssl.h")
message(FATAL_ERROR "OpenSSL headers not found in ${OPENSSL_INCLUDE_DIR}")
endif()
# SQLite3
set(SQLITE3_ROOT_DIR "${THIRD_PARTY_DIR}/sqlite3/")
set(SQLITE3_INCLUDE_DIR "${SQLITE3_ROOT_DIR}/include")
set(SQLITE3_LIBRARIE "${SQLITE3_ROOT_DIR}/lib/sqlite3.lib")
# tinyxml2
set(TINYXML2_INCLUDE_DIR "${THIRD_PARTY_DIR}/tinyxml2-6.0.0/")
file(GLOB TINYXML2_SOURCES "${THIRD_PARTY_DIR}/tinyxml2-6.0.0/*.cpp")
else()
find_package(nlohmann_json REQUIRED)
find_package(Threads REQUIRED)
find_package(SQLite3 REQUIRED)
endif()
find_package(OpenSSL REQUIRED)
if(NOT fastcdr_FOUND)
find_package(fastcdr 2 REQUIRED)
endif()
if(NOT fastdds_FOUND)
find_package(fastdds 3 REQUIRED)
endif()
file(GLOB DDS_XNIDL_SOURCES_CXX "XNIDL/*.cxx")
set(XNCORE_SOURCES "")
set(XNCORE_IDL_SOURCES "")
find_package(nlohmann_json REQUIRED)
find_package(Threads REQUIRED)
find_package(OpenSSL REQUIRED)
find_package(SQLite3 REQUIRED)
add_subdirectory(XNBaseFrameObject)
add_subdirectory(XNDDSInterface)
add_subdirectory(XNDDSManager)
add_subdirectory(XNEventManager)
add_subdirectory(XNFramework)
add_subdirectory(XNGlobalDefine)
add_subdirectory(XNLogger)
add_subdirectory(XNModelManager)
add_subdirectory(XNModelObject)
add_subdirectory(XNObject)
add_subdirectory(XNScenarioManager)
add_subdirectory(XNServiceManager)
add_subdirectory(XNServiceObject)
add_subdirectory(XNThreadManager)
add_subdirectory(XNThreadObject)
add_subdirectory(XNTimeManager)
add_subdirectory(XNIDL)
add_library(XNCore SHARED
XNCore_global.h
XNCore_Function.cpp
XNTypeTraits.h
XNByteArray.h
XNObject.h
XNObject.cpp
XNObject_p.h
XNFramework.cpp
XNFramework.h
XNFramework_p.h
XNBaseFrameObject.h
XNBaseFrameObject.cpp
XNBaseFrameObject_p.h
XNLogger.h
XNLogger.cpp
XNTimeManager.h
XNTimeManager_p.h
XNTimeManager.cpp
XNThread.h
XNThread.cpp
XNThread_p.h
XNThreadManager.h
XNThreadManager_p.h
XNThreadManager.cpp
XNModelObject.h
XNModelObject_p.h
XNModelObject.cpp
XNModelManager.h
XNModelManager_p.h
XNModelManager.cpp
XNScenarioManager.h
XNScenarioManager_p.h
XNScenarioManager.cpp
XNDDSManager.h
XNDDSManager.cpp
XNServiceManager.h
XNServiceManager_p.h
XNServiceManager.cpp
XNEventManager.h
XNEventManager_p.h
XNEventManager.cpp
XNServiceObject.h
XNServiceObject_p.h
XNServiceObject.cpp
XNDDSInterface.h
XNDDSInterface.cpp
${DDS_XNIDL_SOURCES_CXX}
)
if(WIN32)
add_library(XNCore SHARED
${XNCORE_SOURCES}
${XNCORE_IDL_SOURCES}
${TINYXML2_SOURCES}
${THIRD_PARTY_DIR}/nlohmann/json.hpp
)
target_include_directories(XNCore PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${OPENSSL_INCLUDE_DIR}
${SQLITE3_INCLUDE_DIR}
${TINYXML2_INCLUDE_DIR}
)
else()
add_library(XNCore SHARED
${XNCORE_SOURCES}
${XNCORE_IDL_SOURCES}
)
target_include_directories(XNCore PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
)
endif()
if(WIN32)
target_link_libraries(XNCore PRIVATE
${CMAKE_THREAD_LIBS_INIT}
fastcdr
fastdds
pthread
OpenSSL::SSL
OpenSSL::Crypto
nlohmann_json
sqlite3
dl
)
${CMAKE_THREAD_LIBS_INIT}
fastcdr
fastdds
OpenSSL::SSL
OpenSSL::Crypto
${SQLITE3_LIBRARIE}
)
else()
target_link_libraries(XNCore PRIVATE
${CMAKE_THREAD_LIBS_INIT}
fastcdr
fastdds
pthread
OpenSSL::SSL
OpenSSL::Crypto
nlohmann_json
sqlite3
tinyxml2
dl
)
endif()
target_compile_definitions(XNCore PRIVATE XNCORE_LIBRARY)
@ -97,11 +141,9 @@ install(TARGETS XNCore
RUNTIME DESTINATION .
)
#
file(GLOB HEADER_FILES "*.h")
# 使 install
install(FILES ${HEADER_FILES} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/XNCore)
file(GLOB_RECURSE ALL_HEADERS "*.h")
install(FILES ${ALL_HEADERS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/XNCore)
file(GLOB IDL_FILES "XNIDL/*")
install(FILES ${IDL_FILES} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/XNIDL)

View File

@ -0,0 +1,7 @@
set(XNBASEFRAMEOBJECT_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/XNBaseFrameObject.h
${CMAKE_CURRENT_SOURCE_DIR}/XNBaseFrameObject_p.h
${CMAKE_CURRENT_SOURCE_DIR}/XNBaseFrameObject.cpp
)
set(XNCORE_SOURCES ${XNCORE_SOURCES} ${XNBASEFRAMEOBJECT_SOURCES} PARENT_SCOPE)

View File

@ -1,99 +0,0 @@
#pragma once
#include <vector>
#include <cstdint>
#include <cstring>
/**
* @brief
* @details QByteArray的功能
*/
class XNByteArray
{
public:
XNByteArray() = default;
explicit XNByteArray(size_t size) : data_(size) {}
/**
* @brief
* @param buffer
* @param size
*/
XNByteArray(const uint8_t *buffer, size_t size) : data_(buffer, buffer + size) {}
/**
* @brief
* @return
*/
uint8_t *data() { return data_.data(); }
/**
* @brief
* @return
*/
const uint8_t *data() const { return data_.data(); }
/**
* @brief
* @return
*/
size_t size() const { return data_.size(); }
/**
* @brief
* @param size
*/
void resize(size_t size) { data_.resize(size); }
/**
* @brief
*/
void clear() { data_.clear(); }
/**
* @brief
* @param buffer
* @param size
*/
void append(const uint8_t *buffer, size_t size)
{
size_t oldSize = data_.size();
data_.resize(oldSize + size);
std::memcpy(data_.data() + oldSize, buffer, size);
}
/**
* @brief XNByteArray
* @param other XNByteArray
*/
void append(const XNByteArray &other) { append(other.data(), other.size()); }
/**
* @brief
* @param index
* @return
*/
uint8_t &operator[](size_t index) { return data_[index]; }
/**
* @brief
* @param index
* @return
*/
const uint8_t &operator[](size_t index) const { return data_[index]; }
/**
* @brief
* @return
*/
bool isEmpty() const { return data_.empty(); }
/**
* @brief
* @param size
*/
void reserve(size_t size) { data_.reserve(size); }
private:
std::vector<uint8_t> data_;
};

View File

@ -1,58 +0,0 @@
#include "XNCore_global.h"
namespace XNSim
{
XNTimePoint parseISOTime(const std::string &timeStr)
{
std::tm tm = {};
std::istringstream ss(timeStr);
ss >> std::get_time(&tm, "%Y-%m-%dT%H:%M:%S");
auto tp = std::chrono::system_clock::from_time_t(std::mktime(&tm));
return tp;
}
// 辅助函数:分割字符串
std::vector<std::string> split(const std::string &str, const std::string &delim)
{
std::vector<std::string> tokens;
size_t prev = 0, pos = 0;
do {
pos = str.find(delim, prev);
if (pos == std::string::npos)
pos = str.length();
std::string token = str.substr(prev, pos - prev);
if (!token.empty())
tokens.push_back(token);
prev = pos + delim.length();
} while (pos < str.length() && prev < str.length());
return tokens;
}
// 辅助函数:获取文件名(不含扩展名)
std::string getFileNameWithoutExt(const std::string &path)
{
size_t lastDot = path.find_last_of('.');
if (lastDot != std::string::npos) {
return path.substr(0, lastDot);
}
return path;
}
/**
* @brief
* @param str
* @param defaultValue
* @return
*/
int safe_stoi(const std::string &str, int defaultValue)
{
if (str.empty()) {
return defaultValue;
}
try {
return std::stoi(str);
} catch (const std::exception &) {
return defaultValue;
}
}
} // namespace XNSim

View File

@ -1,291 +0,0 @@
#pragma once
#if defined(XNCORE_LIBRARY)
# define XNCORE_EXPORT __attribute__((visibility("default")))
#else
# define XNCORE_EXPORT __attribute__((visibility("default")))
#endif
#define FORCEINLINE __attribute__((always_inline))
#ifdef __linux__
# include <pthread.h>
# include <sched.h>
# include <sys/timeb.h>
# include <sys/mman.h>
# include <sys/stat.h>
# include <errno.h>
# include <time.h>
# include <memory>
# include <errno.h>
# include <unistd.h>
# include <limits.h>
# include <functional>
# include <map>
# include <unordered_map>
# include <vector>
# include <set>
# include <any>
# include <string>
# include <thread>
# include <mutex>
# include <condition_variable>
# include <queue>
# include <tinyxml2.h>
# include <chrono>
# include <iomanip>
# include <sstream>
# include <dlfcn.h>
# include <filesystem>
# include <array>
# include <cstring>
# include <iostream>
# include <sqlite3.h>
# include <nlohmann/json.hpp>
#endif
#include <fastdds/dds/domain/DomainParticipant.hpp>
#include <fastdds/dds/domain/DomainParticipantFactory.hpp>
#include <fastdds/dds/publisher/DataWriter.hpp>
#include <fastdds/dds/publisher/Publisher.hpp>
#include <fastdds/dds/subscriber/DataReader.hpp>
#include <fastdds/dds/subscriber/Subscriber.hpp>
#include <fastdds/dds/topic/TypeSupport.hpp>
#include <fastdds/dds/subscriber/DataReaderListener.hpp>
#include <fastcdr/xcdr/optional.hpp>
#define FAST_DDS_MACRO eprosima::fastdds::dds
using XN_JSON = nlohmann::json;
/**
* @brief Hz
*/
#define BASE_RUN_FREQ 100.0
/**
* @brief
*/
#define BASE_RUN_INTER (1.0E9 / BASE_RUN_FREQ)
//模型周期性回调函数类型别名
using XNCallBack = std::function<void()>;
//DDS回调函数类型别名
using XNDDSCallBack = std::function<void(void *)>;
//事件回调函数类型别名
using XNEventCallback = std::function<void(const std::any &)>;
/**
* @brief
* @details 线
*/
struct PERIOD_INFO {
/**
* @brief
*/
timespec next_period;
/**
* @brief
*/
long period_ns;
};
/**
* @brief
*/
using XNTimePoint = std::chrono::system_clock::time_point;
/**
* @brief
*/
enum class RunStatus {
/**
* @brief
*/
NotStart = 0,
/**
* @brief
*/
Runing,
/**
* @brief
*/
Suspend,
/**
* @brief
*/
Aborted,
/**
* @brief
*/
Finished
};
/**
* @brief 仿
*/
enum class SimControlCmd {
/**
* @brief
*/
Start,
/**
* @brief
*/
Continue,
/**
* @brief
*/
Suspend,
/**
* @brief
*/
Abort
};
/**
* @brief
*/
enum class FreqLevel {
/**
* @brief
*/
BaseFreq = 0, // 120/100/60 Hz
/**
* @brief
*/
HalfFreq, // 60/50/30 Hz
/**
* @brief
*/
QuarterFreq, // 30/25/15 Hz
/**
* @brief
*/
EighthFreq, // 15/12.5/7.5 Hz
/**
* @brief
*/
SixteenthFreq, // 7.5/6.25/3.75 Hz
/**
* @brief
*/
ThirtyTwothFreq, // 3.75/3.125/1.875 Hz
};
/**
* @brief
*/
enum class XNFrameObjectStatus {
/**
* @brief
*/
NotReady = 0,
/**
* @brief
*/
Initialized,
/**
* @brief
*/
Ready,
/**
* @brief
*/
Unknown
};
template <class ToType, class FromType>
FORCEINLINE ToType XNStaticCastHelper(const FromType &from)
{
return std::static_pointer_cast<typename ToType::element_type>(from);
}
template <class ToType, class FromType>
FORCEINLINE ToType XNCastHelper(const FromType &from)
{
return std::dynamic_pointer_cast<typename ToType::element_type>(from);
}
#define XN_CAST(from, to) XNStaticCastHelper<to>(from)
#define XN_THISPTR std::static_pointer_cast<ThisType>(shared_from_this())
#define XNCLASS_PTR_DECLARE(a) \
using a##Ptr = std::shared_ptr<class a>; \
using a##WPtr = std::weak_ptr<class a>; \
using a##UPtr = std::unique_ptr<class a>; \
using a##ConsPtr = std::shared_ptr<const class a>;
#define XNSTRUCT_PTR_DECLARE(a) \
using a##Ptr = std::shared_ptr<struct a>; \
using a##WPtr = std::weak_ptr<struct a>; \
using a##UPtr = std::unique_ptr<struct a>; \
using a##ConsPtr = std::shared_ptr<const struct a>;
#define XN_NOCOPYABLE(Class) \
public: \
using NoCopyable = Class; \
\
private: \
Class(const Class &) = delete; \
Class &operator=(const Class &) = delete;
#define XN_DECLARE_PRIVATE(Class) \
XN_NOCOPYABLE(Class) \
protected: \
friend class Class##Private; \
inline Class##Private *GetPP() const \
{ \
return reinterpret_cast<Class##Private *>(_Private_Ptr); \
} \
using PrivateType = Class##Private;
#define T_D() PrivateType *const d = GetPP()
struct XNNullClass {
};
#define XN_METATYPE_P(cls) \
public: \
using ThisType = cls; \
using SuperType = XNNullClass;
#define XN_METATYPE(cls, sup) \
public: \
using ThisType = cls; \
using SuperType = sup;
#define XN_UNUSED(x) (void)x
namespace XNSim
{
template <typename T>
constexpr typename std::underlying_type<T>::type enumValue(T e)
{
return static_cast<typename std::underlying_type<T>::type>(e);
}
/**
* @brief ISO格式的时间字符串转换为系统时间点
* @param timeStr ISO格式的时间字符串 (YYYY-MM-DDTHH:mm:ss)
* @return
*/
extern "C" XNTimePoint XNCORE_EXPORT parseISOTime(const std::string &timeStr);
extern "C" std::vector<std::string> XNCORE_EXPORT split(const std::string &str,
const std::string &delim);
extern "C" std::string XNCORE_EXPORT getFileNameWithoutExt(const std::string &path);
extern "C" int XNCORE_EXPORT safe_stoi(const std::string &str, int defaultValue = 0);
inline std::string getStringFromSqlite3(sqlite3_stmt *stmt, int column)
{
const char *text = reinterpret_cast<const char *>(sqlite3_column_text(stmt, column));
if (text == nullptr) {
return "";
}
return std::string(text);
}
} // namespace XNSim

View File

@ -0,0 +1,6 @@
set(XNDDSINTERFACE_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/XNDDSInterface.h
${CMAKE_CURRENT_SOURCE_DIR}/XNDDSInterface.cpp
)
set(XNCORE_SOURCES ${XNCORE_SOURCES} ${XNDDSINTERFACE_SOURCES} PARENT_SCOPE)

View File

@ -0,0 +1,6 @@
set(XNDDSMANAGER_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/XNDDSManager.h
${CMAKE_CURRENT_SOURCE_DIR}/XNDDSManager.cpp
)
set(XNCORE_SOURCES ${XNCORE_SOURCES} ${XNDDSMANAGER_SOURCES} PARENT_SCOPE)

View File

View File

View File

@ -0,0 +1,7 @@
set(XNEVENTMANAGER_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/XNEventManager.h
${CMAKE_CURRENT_SOURCE_DIR}/XNEventManager_p.h
${CMAKE_CURRENT_SOURCE_DIR}/XNEventManager.cpp
)
set(XNCORE_SOURCES ${XNCORE_SOURCES} ${XNEVENTMANAGER_SOURCES} PARENT_SCOPE)

View File

View File

View File

View File

@ -0,0 +1,7 @@
set(XNFRAMEWORK_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/XNFramework.h
${CMAKE_CURRENT_SOURCE_DIR}/XNFramework_p.h
${CMAKE_CURRENT_SOURCE_DIR}/XNFramework.cpp
)
set(XNCORE_SOURCES ${XNCORE_SOURCES} ${XNFRAMEWORK_SOURCES} PARENT_SCOPE)

View File

View File

View File

@ -1,85 +1,85 @@
/**
* @file XNFramework_p.h
* @author jinchao
* @brief
* @version 1.0
* @date 2025-01-08
*
* @copyright Copyright (c) 2025 COMAC
*
*/
#pragma once
#include "XNObject_p.h"
/**
* @brief
*/
struct XNFrameworkPrivate : public XNObjectPrivate {
/**
* @brief DDS管理器
*/
XNDDSManagerPtr ddsManager;
/**
* @brief
*/
XNEventManagerPtr eventManager;
/**
* @brief
*/
XNModelManagerPtr modelManager;
/**
* @brief
*/
XNScenarioManagerPtr scenarioManager;
/**
* @brief
*/
XNServiceManagerPtr serviceManager;
/**
* @brief 线
*/
XNThreadManagerPtr threadManager;
/**
* @brief
*/
XNTimeManagerPtr timeManager;
/**
* @brief
*/
std::string workPath;
/**
* @brief
*/
std::string modelPath;
/**
* @brief
*/
std::string servicePath;
/**
* @brief CPU亲和性
*/
uint32_t uCpuAffinity;
/**
* @brief XML
*/
std::string scenarioXml;
/**
* @brief ID
*/
uint32_t configId;
};
/**
* @file XNFramework_p.h
* @author jinchao
* @brief
* @version 1.0
* @date 2025-01-08
*
* @copyright Copyright (c) 2025 COMAC
*
*/
#pragma once
#include "XNObject_p.h"
/**
* @brief
*/
struct XNFrameworkPrivate : public XNObjectPrivate {
/**
* @brief DDS管理器
*/
XNDDSManagerPtr ddsManager;
/**
* @brief
*/
XNEventManagerPtr eventManager;
/**
* @brief
*/
XNModelManagerPtr modelManager;
/**
* @brief
*/
XNScenarioManagerPtr scenarioManager;
/**
* @brief
*/
XNServiceManagerPtr serviceManager;
/**
* @brief 线
*/
XNThreadManagerPtr threadManager;
/**
* @brief
*/
XNTimeManagerPtr timeManager;
/**
* @brief
*/
std::string workPath;
/**
* @brief
*/
std::string modelPath;
/**
* @brief
*/
std::string servicePath;
/**
* @brief CPU亲和性
*/
uint32_t uCpuAffinity;
/**
* @brief XML
*/
std::string scenarioXml;
/**
* @brief ID
*/
uint32_t configId;
};

View File

@ -0,0 +1,20 @@
set(XNGLOBALDEFINE_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/XNByteArray.h
${CMAKE_CURRENT_SOURCE_DIR}/XNCore_global.h
${CMAKE_CURRENT_SOURCE_DIR}/XNDataBase.h
${CMAKE_CURRENT_SOURCE_DIR}/XNDDS.h
${CMAKE_CURRENT_SOURCE_DIR}/XNDefine.h
${CMAKE_CURRENT_SOURCE_DIR}/XNEnum.h
${CMAKE_CURRENT_SOURCE_DIR}/XNFile.h
${CMAKE_CURRENT_SOURCE_DIR}/XNJson.h
${CMAKE_CURRENT_SOURCE_DIR}/XNMemory.h
${CMAKE_CURRENT_SOURCE_DIR}/XNMeta.h
${CMAKE_CURRENT_SOURCE_DIR}/XNString.h
${CMAKE_CURRENT_SOURCE_DIR}/XNThread.h
${CMAKE_CURRENT_SOURCE_DIR}/XNTime.h
${CMAKE_CURRENT_SOURCE_DIR}/XNType.h
${CMAKE_CURRENT_SOURCE_DIR}/XNTypeTraits.h
${CMAKE_CURRENT_SOURCE_DIR}/XNXml.h
)
set(XNCORE_SOURCES ${XNCORE_SOURCES} ${XNGLOBALDEFINE_SOURCES} PARENT_SCOPE)

View File

@ -0,0 +1,100 @@
#pragma once
#include "XNCore_global.h"
#include "XNType.h"
#include <vector>
namespace XNSim {
/**
* @brief
* @details QByteArray的功能
*/
class XNByteArray {
public:
XNByteArray() = default;
explicit XNByteArray(XN_SIZE size) : data_(size) {}
/**
* @brief
* @param buffer
* @param size
*/
XNByteArray(const XN_UINT8 *buffer, XN_SIZE size)
: data_(buffer, buffer + size) {}
/**
* @brief
* @return
*/
XN_UINT8 *data() { return data_.data(); }
/**
* @brief
* @return
*/
const XN_UINT8 *data() const { return data_.data(); }
/**
* @brief
* @return
*/
XN_SIZE size() const { return data_.size(); }
/**
* @brief
* @param size
*/
void resize(XN_SIZE size) { data_.resize(size); }
/**
* @brief
*/
void clear() { data_.clear(); }
/**
* @brief
* @param buffer
* @param size
*/
void append(const XN_UINT8 *buffer, XN_SIZE size) {
XN_SIZE oldSize = data_.size();
data_.resize(oldSize + size);
std::memcpy(data_.data() + oldSize, buffer, size);
}
/**
* @brief XNByteArray
* @param other XNByteArray
*/
void append(const XNByteArray &other) { append(other.data(), other.size()); }
/**
* @brief
* @param index
* @return
*/
XN_UINT8 &operator[](XN_SIZE index) { return data_[index]; }
/**
* @brief
* @param index
* @return
*/
const XN_UINT8 &operator[](XN_SIZE index) const { return data_[index]; }
/**
* @brief
* @return
*/
XN_BOOL isEmpty() const { return data_.empty(); }
/**
* @brief
* @param size
*/
void reserve(XN_SIZE size) { data_.reserve(size); }
private:
std::vector<XN_UINT8> data_;
};
} // namespace XNSim

View File

@ -0,0 +1,40 @@
#pragma once
// 导出宏定义
#if defined(_WIN32)
#if defined(XNCORE_LIBRARY)
#define XNCORE_EXPORT __declspec(dllexport)
#else
#define XNCORE_EXPORT __declspec(dllimport)
#endif
#elif defined(__linux__)
#if defined(XNCORE_LIBRARY)
#define XNCORE_EXPORT __attribute__((visibility("default")))
#else
#define XNCORE_EXPORT __attribute__((visibility("default")))
#endif
#endif
// 内联宏定义
#if defined(_WIN32)
#define FORCEINLINE __forceinline
#else
#define FORCEINLINE __attribute__((always_inline))
#endif
// 平台相关头文件
#if defined(_WIN32)
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#elif defined(__linux__)
#include <dlfcn.h>
#include <errno.h>
#include <limits.h>
#include <pthread.h>
#include <sched.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/timeb.h>
#include <unistd.h>
#endif

View File

@ -0,0 +1,20 @@
#pragma once
// FastDDS头文件
#include <fastcdr/xcdr/optional.hpp>
#include <fastdds/dds/domain/DomainParticipant.hpp>
#include <fastdds/dds/domain/DomainParticipantFactory.hpp>
#include <fastdds/dds/publisher/DataWriter.hpp>
#include <fastdds/dds/publisher/Publisher.hpp>
#include <fastdds/dds/subscriber/DataReader.hpp>
#include <fastdds/dds/subscriber/DataReaderListener.hpp>
#include <fastdds/dds/subscriber/Subscriber.hpp>
#include <fastdds/dds/topic/TypeSupport.hpp>
#include <functional>
// FastDDS宏定义
#define XN_DDS eprosima::fastdds::dds
namespace XNSim {
// DDS回调函数类型别名
using XNDDSCallBack = std::function<void(void *)>;
} // namespace XNSim

View File

@ -0,0 +1,19 @@
#pragma once
// sqlite3头文件
#include "XNCore_global.h"
#include "XNString.h"
#include "XNType.h"
#include <sqlite3.h>
namespace XNSim {
FORCEINLINE XN_STRING getStringFromSqlite3(sqlite3_stmt *stmt,
XN_INT32 column) {
const char *text =
reinterpret_cast<const char *>(sqlite3_column_text(stmt, column));
if (text == nullptr) {
return "";
}
return XN_STRING(text);
}
} // namespace XNSim

View File

@ -0,0 +1,36 @@
#pragma once
#include "XNByteArray.h"
#include "XNCore_global.h"
#include "XNDDS.h"
#include "XNDataBase.h"
#include "XNEnum.h"
#include "XNFile.h"
#include "XNJson.h"
#include "XNMemory.h"
#include "XNMeta.h"
#include "XNString.h"
#include "XNThread.h"
#include "XNTime.h"
#include "XNType.h"
#include "XNTypeTraits.h"
// 标准库头文件
#include <cstddef>
#include <cstring>
#include <initializer_list>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <unordered_map>
/**
* @brief Hz
*/
#define BASE_RUN_FREQ 100.0
/**
* @brief
*/
#define BASE_RUN_INTER (1.0E9 / BASE_RUN_FREQ)

View File

@ -0,0 +1,104 @@
#pragma once
namespace XNSim {
/**
* @brief
*/
enum class RunStatus {
/**
* @brief
*/
NotStart = 0,
/**
* @brief
*/
Runing,
/**
* @brief
*/
Suspend,
/**
* @brief
*/
Aborted,
/**
* @brief
*/
Finished
};
/**
* @brief 仿
*/
enum class SimControlCmd {
/**
* @brief
*/
Start = 0,
/**
* @brief
*/
Continue,
/**
* @brief
*/
Suspend,
/**
* @brief
*/
Abort
};
/**
* @brief
*/
enum class FreqLevel {
/**
* @brief
*/
BaseFreq = 0, // 120/100/60 Hz
/**
* @brief
*/
HalfFreq, // 60/50/30 Hz
/**
* @brief
*/
QuarterFreq, // 30/25/15 Hz
/**
* @brief
*/
EighthFreq, // 15/12.5/7.5 Hz
/**
* @brief
*/
SixteenthFreq, // 7.5/6.25/3.75 Hz
/**
* @brief
*/
ThirtyTwothFreq, // 3.75/3.125/1.875 Hz
};
/**
* @brief
*/
enum class XNFrameObjectStatus {
/**
* @brief
*/
NotReady = 0,
/**
* @brief
*/
Initialized,
/**
* @brief
*/
Ready,
/**
* @brief
*/
Unknown
};
} // namespace XNSim

View File

@ -0,0 +1,36 @@
#pragma once
#include "XNCore_global.h"
#include "XNString.h"
#include "XNType.h"
#include <filesystem>
#include <fstream>
namespace XNSim {
using XN_PATH = std::filesystem::path;
// 流相关类型别名
using XN_OFSTREAM = std::ofstream;
using XN_IFSTREAM = std::ifstream;
using XN_FSTREAM = std::fstream;
FORCEINLINE XN_PATH getCurrentPath() { return std::filesystem::current_path(); }
FORCEINLINE bool isExist(const XN_PATH &path) {
return std::filesystem::exists(path);
}
FORCEINLINE bool isDirectory(const XN_PATH &path) {
return std::filesystem::is_directory(path);
}
FORCEINLINE void createDirectory(const XN_PATH &path) {
std::filesystem::create_directories(path);
}
FORCEINLINE XN_STRING getFileNameWithoutExt(const XN_STRING &path) {
XN_SIZE lastDot = path.find_last_of('.');
if (lastDot != XN_STRING::npos) {
return path.substr(0, lastDot);
}
return path;
}
} // namespace XNSim

View File

@ -0,0 +1,9 @@
#pragma once
// json头文件
#include <nlohmann/json.hpp>
namespace XNSim {
// json类型别名
using XN_JSON = nlohmann::json;
} // namespace XNSim

View File

@ -0,0 +1,42 @@
#pragma once
#include "XNCore_global.h"
#include <memory>
namespace XNSim {
template <typename T>
using XN_ENABLE_SHARED_FROM_THIS = std::enable_shared_from_this<T>;
// 静态指针类型转换辅助函数
template <class ToType, class FromType>
FORCEINLINE ToType XNStaticCastHelper(const FromType &from) {
return std::static_pointer_cast<typename ToType::element_type>(from);
}
// 动态指针类型转换辅助函数
template <class ToType, class FromType>
FORCEINLINE ToType XNCastHelper(const FromType &from) {
return std::dynamic_pointer_cast<typename ToType::element_type>(from);
}
} // namespace XNSim
// 静态类型转换宏
#define XN_CAST(from, to) XNStaticCastHelper<to>(from)
// 获取当前对象的智能指针
#define XN_THISPTR std::static_pointer_cast<ThisType>(shared_from_this())
// 类智能指针声明宏
#define XNCLASS_PTR_DECLARE(a) \
using a##Ptr = std::shared_ptr<class a>; \
using a##WPtr = std::weak_ptr<class a>; \
using a##UPtr = std::unique_ptr<class a>; \
using a##ConsPtr = std::shared_ptr<const class a>;
// 结构体智能指针声明宏
#define XNSTRUCT_PTR_DECLARE(a) \
using a##Ptr = std::shared_ptr<struct a>; \
using a##WPtr = std::weak_ptr<struct a>; \
using a##UPtr = std::unique_ptr<struct a>; \
using a##ConsPtr = std::shared_ptr<const struct a>;

View File

@ -0,0 +1,45 @@
#pragma once
#include "XNCore_global.h"
namespace XNSim {
// 空类宏
struct XNNullClass {};
} // namespace XNSim
// 禁止拷贝构造和赋值宏
#define XN_NOCOPYABLE(Class) \
public: \
using NoCopyable = Class; \
\
private: \
Class(const Class &) = delete; \
Class &operator=(const Class &) = delete;
// 声明私有类宏
#define XN_DECLARE_PRIVATE(Class) \
XN_NOCOPYABLE(Class) \
protected: \
friend class Class##Private; \
inline Class##Private *GetPP() const { \
return reinterpret_cast<Class##Private *>(_Private_Ptr); \
} \
using PrivateType = Class##Private;
// 获取私有类指针宏
#define T_D() PrivateType *const d = GetPP()
// 元类型声明宏
#define XN_METATYPE_P(cls) \
public: \
using ThisType = cls; \
using SuperType = XNSim::XNNullClass;
// 元类型声明宏
#define XN_METATYPE(cls, sup) \
public: \
using ThisType = cls; \
using SuperType = sup;
// 忽略参数宏
#define XN_UNUSED(x) (void)x

View File

@ -0,0 +1,73 @@
#pragma once
#include "XNCore_global.h"
#include "XNType.h"
#include <string>
#include <vector>
namespace XNSim {
// 字符串类型抽象
using XN_STRING = std::string;
using XN_WSTRING = std::wstring;
using XN_STRINGLIST = std::vector<XN_STRING>;
using XN_WSTRINGLIST = std::vector<XN_WSTRING>;
// 字符串转换辅助函数
template <typename T> FORCEINLINE XN_STRING To_XNString(const T &value) {
return std::to_string(value);
}
template <typename T> FORCEINLINE XN_WSTRING To_XNWString(const T &value) {
return std::to_wstring(value);
}
FORCEINLINE XN_STRINGLIST XNSplit(const XN_STRING &str,
const XN_STRING &delim) {
XN_STRINGLIST tokens;
XN_SIZE prev = 0, pos = 0;
do {
pos = str.find(delim, prev);
if (pos == XN_STRING::npos)
pos = str.length();
XN_STRING token = str.substr(prev, pos - prev);
if (!token.empty())
tokens.push_back(token);
prev = pos + delim.length();
} while (pos < str.length() && prev < str.length());
return tokens;
}
FORCEINLINE XN_INT32 XNSafe_stoi(const XN_STRING &str,
XN_INT32 defaultValue = 0) {
if (str.empty()) {
return defaultValue;
}
try {
return std::stoi(str);
} catch (const std::exception &) {
return defaultValue;
}
}
FORCEINLINE XN_DOUBLE XNSafe_stod(const XN_STRING &str,
XN_DOUBLE defaultValue = 0) {
if (str.empty()) {
return defaultValue;
}
try {
return std::stod(str);
} catch (const std::exception &) {
return defaultValue;
}
}
FORCEINLINE XN_INT64 XNSafe_stoll(const XN_STRING &str,
XN_INT64 defaultValue = 0) {
if (str.empty()) {
return defaultValue;
}
try {
return std::stoll(str);
} catch (const std::exception &) {
return defaultValue;
}
}
} // namespace XNSim

View File

@ -0,0 +1,19 @@
#pragma once
#include <any>
#include <condition_variable>
#include <functional>
#include <mutex>
#include <thread>
namespace XNSim {
// 线程相关抽象
using XN_MUTEX = std::mutex;
using XN_CV = std::condition_variable;
// 模型周期性回调函数类型别名
using XNCallBack = std::function<void()>;
// 事件回调函数类型别名
using XNEventCallback = std::function<void(const std::any &)>;
} // namespace XNSim

View File

@ -0,0 +1,42 @@
#pragma once
#include "XNCore_global.h"
#include "XNString.h"
#include "XNType.h"
#include <chrono>
#include <iomanip>
#include <sstream>
#include <time.h>
namespace XNSim {
/**
* @brief
* @details 线
*/
struct PERIOD_INFO {
/**
* @brief
*/
timespec next_period;
/**
* @brief
*/
XN_INT64 period_ns;
};
// 系统时间点类型别名
using XNTimePoint = std::chrono::system_clock::time_point;
/**
* @brief ISO格式的时间字符串转换为系统时间点
* @param timeStr ISO格式的时间字符串 (YYYY-MM-DDTHH:mm:ss)
* @return
*/
FORCEINLINE XNTimePoint parseISOTime(const XN_STRING &timeStr) {
std::tm tm = {};
std::istringstream ss(timeStr);
ss >> std::get_time(&tm, "%Y-%m-%dT%H:%M:%S");
auto tp = std::chrono::system_clock::from_time_t(std::mktime(&tm));
return tp;
}
} // namespace XNSim

View File

@ -0,0 +1,19 @@
#pragma once
#include <cstdint>
namespace XNSim {
// 基础类型抽象
using XN_INT8 = int8_t;
using XN_UINT8 = uint8_t;
using XN_INT16 = int16_t;
using XN_UINT16 = uint16_t;
using XN_INT32 = int32_t;
using XN_UINT32 = uint32_t;
using XN_INT64 = int64_t;
using XN_UINT64 = uint64_t;
using XN_FLOAT = float;
using XN_DOUBLE = double;
using XN_BOOL = bool;
using XN_SIZE = size_t;
} // namespace XNSim

View File

@ -0,0 +1,70 @@
#pragma once
#include <array>
#include <type_traits>
namespace XNSim {
// 类型检查
template <typename T, typename U>
inline constexpr bool is_same_v = std::is_same_v<T, U>;
// 算术类型检查
template <typename T>
inline constexpr bool is_arithmetic_v = std::is_arithmetic_v<T>;
// 可转换类型检查
template <typename T, typename U>
inline constexpr bool is_convertible_v = std::is_convertible_v<T, U>;
// 数组类型检查
namespace TypeTraits {
template <typename T> struct is_std_array : std::false_type {};
template <typename T, std::size_t N>
struct is_std_array<std::array<T, N>> : std::true_type {};
} // namespace TypeTraits
// 数组类型检查简化使用
template <typename T>
inline constexpr bool is_array_v = TypeTraits::is_std_array<T>::value;
// 获取数组大小
namespace TypeTraits {
template <typename T>
struct array_size : std::integral_constant<std::size_t, 1> {};
template <typename T, std::size_t N>
struct array_size<std::array<T, N>> : std::integral_constant<std::size_t, N> {};
} // namespace TypeTraits
// 获取数组大小简化使用
template <typename T>
inline constexpr std::size_t array_size_v = TypeTraits::array_size<T>::value;
// 获取类型大小
template <typename T> constexpr size_t getTypeSize() {
if constexpr (is_array_v<T>) {
// 对于std::array计算所有元素的总大小
return getTypeSize<typename T::value_type>() * array_size_v<T>;
} else {
return sizeof(T);
}
}
// 获取数组总大小
template <typename T> constexpr std::size_t arrayTotalSize(const T &arr) {
if constexpr (is_array_v<T>) {
// 对于std::array计算所有元素的总大小
return getTypeSize<typename T::value_type>() * array_size_v<T>;
} else {
return 1;
}
}
// 枚举值获取函数
template <typename T>
constexpr typename std::underlying_type<T>::type enumValue(T e) {
return static_cast<typename std::underlying_type<T>::type>(e);
}
} // namespace XNSim

View File

@ -0,0 +1,4 @@
#pragma once
// tinyxml2头文件
#include <tinyxml2.h>

View File

@ -0,0 +1,11 @@
set(XNIDL_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/XNSimStatus.hpp
${CMAKE_CURRENT_SOURCE_DIR}/XNSimStatusCdrAux.hpp
${CMAKE_CURRENT_SOURCE_DIR}/XNSimStatusCdrAux.ipp
${CMAKE_CURRENT_SOURCE_DIR}/XNSimStatusPubSubTypes.cxx
${CMAKE_CURRENT_SOURCE_DIR}/XNSimStatusPubSubTypes.hpp
${CMAKE_CURRENT_SOURCE_DIR}/XNSimStatusTypeObjectSupport.cxx
${CMAKE_CURRENT_SOURCE_DIR}/XNSimStatusTypeObjectSupport.hpp
)
set(XNCORE_IDL_SOURCES ${XNCORE_IDL_SOURCES} ${XNIDL_SOURCES} PARENT_SCOPE)

View File

@ -1,118 +0,0 @@
#include "XNLogger.h"
XNLogger::XNLogger()
: consoleOutputEnabled{true, true, true, true}, fileOutputEnabled{true, true, true, true}
{
// 获取当前工作目录
std::filesystem::path currentDir = std::filesystem::current_path();
std::filesystem::path logDirPath = currentDir / "log";
// 创建 log 文件夹
if (!std::filesystem::exists(logDirPath)) {
std::filesystem::create_directories(logDirPath);
}
// 创建以当前日期和时间命名的日志文件
auto now = std::chrono::system_clock::now();
auto time = std::chrono::system_clock::to_time_t(now);
std::stringstream ss;
ss << std::put_time(std::localtime(&time), "%Y%m%d_%H%M%S");
std::string logFileName = "log_" + ss.str() + ".log";
logFilePath = (logDirPath / logFileName).string();
logFile.open(logFilePath, std::ios::app);
}
XNLogger::~XNLogger()
{
if (logFile.is_open()) {
logFile.close();
}
}
std::string XNLogger::getCurrentTimeString() const
{
auto now = std::chrono::system_clock::now();
auto time = std::chrono::system_clock::to_time_t(now);
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) % 1000;
std::stringstream ss;
ss << std::put_time(std::localtime(&time), "%Y-%m-%d %H:%M:%S");
ss << '.' << std::setfill('0') << std::setw(3) << ms.count();
return ss.str();
}
void XNLogger::log(LogLevel level, const std::string &message)
{
std::lock_guard<std::mutex> locker(mutex);
std::string logMessage =
"[" + getCurrentTimeString() + "] [" + logLevelToString(level) + "] " + message;
std::string coloredMessage;
// 根据日志等级设置颜色
switch (level) {
case Debug:
coloredMessage = COLOR_DEBUG + logMessage + COLOR_RESET;
break;
case Info:
coloredMessage = COLOR_INFO + logMessage + COLOR_RESET;
break;
case Warning:
coloredMessage = COLOR_WARNING + logMessage + COLOR_RESET;
break;
case Error:
coloredMessage = COLOR_ERROR + logMessage + COLOR_RESET;
break;
default:
coloredMessage = logMessage; // 默认无颜色
break;
}
// 控制台输出
if (consoleOutputEnabled[level]) {
if (level == Time) {
// 如果是时间日志,则不换行,回退到该行开始
std::cout << coloredMessage << "\r" << std::flush;
} else {
std::cout << coloredMessage << std::endl;
}
}
// 文件输出
if (fileOutputEnabled[level] && logFile.is_open()) {
if (level == Time) {
logFile << logMessage << "\r" << std::flush;
} else {
logFile << logMessage << std::endl;
}
}
}
void XNLogger::enableConsoleOutput(LogLevel level, bool enable)
{
consoleOutputEnabled[level] = enable;
}
void XNLogger::enableFileOutput(LogLevel level, bool enable)
{
fileOutputEnabled[level] = enable;
}
std::string XNLogger::logLevelToString(LogLevel level) const
{
switch (level) {
case Debug:
return "DEBUG";
case Info:
return "INFO";
case Warning:
return "WARNING";
case Error:
return "ERROR";
case Time:
return "TIME";
default:
return "UNKNOWN";
}
}

View File

@ -1,254 +0,0 @@
/**
* @file XNLogger.h
* @author jinchao
* @brief
* @version 1.0
* @date 2025-01-08
*
* @copyright Copyright (c) 2025 COMAC
*
*/
#pragma once
#include <string>
#include <mutex>
#include <fstream>
#include <chrono>
#include <filesystem>
#include <type_traits>
#include <iostream>
#include <iomanip>
#include <sstream>
/**
* @brief
*/
class XNLogger
{
public:
/**
* @brief
*/
enum LogLevel { Debug, Info, Warning, Error, Time };
/**
* @brief
* @return
*/
static XNLogger &instance()
{
static XNLogger instance;
return instance;
}
/**
* @brief
* @param level
* @param message
*/
void log(LogLevel level, const std::string &message);
/**
* @brief
* @param level
* @param enable
*/
void enableConsoleOutput(LogLevel level, bool enable);
/**
* @brief
* @param level
* @param enable
*/
void enableFileOutput(LogLevel level, bool enable);
private:
/**
* @brief
*/
XNLogger();
/**
* @brief
*/
~XNLogger();
/**
* @brief
*/
XNLogger(const XNLogger &) = delete;
/**
* @brief
*/
XNLogger &operator=(const XNLogger &) = delete;
/**
* @brief
*/
std::string logFilePath;
/**
* @brief
*/
bool consoleOutputEnabled[5];
/**
* @brief
*/
bool fileOutputEnabled[5];
/**
* @brief
*/
std::ofstream logFile;
/**
* @brief
*/
std::mutex mutex;
/**
* @brief
* @param level
* @return
*/
std::string logLevelToString(LogLevel level) const;
/**
* @brief
* @return
*/
std::string getCurrentTimeString() const;
/**
* @brief
*/
const std::string COLOR_RESET = "\033[0m";
/**
* @brief
*/
const std::string COLOR_DEBUG = "\033[34m"; // 蓝色
/**
* @brief
*/
const std::string COLOR_INFO = "\033[32m"; // 绿色
/**
* @brief
*/
const std::string COLOR_WARNING = "\033[33m"; // 黄色
/**
* @brief
*/
const std::string COLOR_ERROR = "\033[31m"; // 红色
};
/**
* @brief
*/
class XNLoggerHelper
{
public:
/**
* @brief
* @tparam Args
* @param level
* @param message
* @param args
*/
template <typename... Args>
inline static typename std::enable_if<(sizeof...(Args) > 0), void>::type
log(XNLogger::LogLevel level, const std::string &message, Args... args)
{
std::string formattedMessage = formatMessage(message, args...);
XNLogger::instance().log(level, formattedMessage);
}
/**
* @brief
* @param level
* @param message
*/
inline static void log(XNLogger::LogLevel level, const std::string &message)
{
XNLogger::instance().log(level, message);
}
private:
/**
* @brief
* @tparam T
* @param arg
* @return
*/
template <typename T>
static std::string convertToString(const T &arg)
{
if constexpr (std::is_arithmetic_v<T>) {
return std::to_string(arg); // 处理数值类型
} else if constexpr (std::is_same_v<T, std::string>) {
return arg;
} else if constexpr (std::is_convertible_v<T, std::string>) {
return std::string(arg);
} else if constexpr (std::is_same_v<T, char *> || std::is_same_v<T, const char *>) {
return std::string(arg);
} else {
static_assert(std::is_arithmetic_v<T> || std::is_same_v<T, std::string>
|| std::is_convertible_v<T, std::string> || std::is_same_v<T, char *>
|| std::is_same_v<T, const char *>,
"A01021001: 不支持的类型转换详见XNLogger.cppline 199");
}
}
/**
* @brief %1%2%3
* @tparam Args
* @param message
* @param args
* @return
*/
template <typename... Args>
static std::string formatMessage(const std::string &message, Args &&...args)
{
static_assert(sizeof...(Args) <= 9,
"A01021002: 单条日志参数数量超过限制详见XNLogger.cppline 216");
std::string result = message;
// 使用初始化列表展开参数包
int index = 1;
// 使用lambda和std::initializer_list展开参数包
(void)std::initializer_list<int>{(
[&result, &index](const auto &value) {
std::string placeholder = "%" + std::to_string(index++);
size_t pos = result.find(placeholder);
if (pos != std::string::npos) {
result.replace(pos, placeholder.length(), convertToString(value));
}
}(args),
0)...};
return result;
}
};
/**
* @brief
*/
#define LOG_DEBUG(message, ...) XNLoggerHelper::log(XNLogger::Debug, message, ##__VA_ARGS__)
/**
* @brief
*/
#define LOG_INFO(message, ...) XNLoggerHelper::log(XNLogger::Info, message, ##__VA_ARGS__)
/**
* @brief
*/
#define LOG_WARNING(message, ...) XNLoggerHelper::log(XNLogger::Warning, message, ##__VA_ARGS__)
/**
* @brief
*/
#define LOG_ERROR(message, ...) XNLoggerHelper::log(XNLogger::Error, message, ##__VA_ARGS__)

View File

@ -0,0 +1,6 @@
set(XNLOGGER_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/XNLogger.h
${CMAKE_CURRENT_SOURCE_DIR}/XNLogger.cpp
)
set(XNCORE_SOURCES ${XNCORE_SOURCES} ${XNLOGGER_SOURCES} PARENT_SCOPE)

View File

@ -0,0 +1,114 @@
#include "XNLogger.h"
XNLogger::XNLogger()
: consoleOutputEnabled{true, true, true, true},
fileOutputEnabled{true, true, true, true} {
// 获取当前工作目录
XN_PATH currentDir = XNGetCurrentPath();
XN_PATH logDirPath = currentDir / "log";
// 创建 log 文件夹
if (!std::filesystem::exists(logDirPath)) {
std::filesystem::create_directories(logDirPath);
}
// 创建以当前日期和时间命名的日志文件
auto now = std::chrono::system_clock::now();
auto time = std::chrono::system_clock::to_time_t(now);
std::stringstream ss;
ss << std::put_time(std::localtime(&time), "%Y%m%d_%H%M%S");
std::string logFileName = "log_" + ss.str() + ".log";
logFilePath = (logDirPath / logFileName).string();
logFile.open(logFilePath, std::ios::app);
}
XNLogger::~XNLogger() {
if (logFile.is_open()) {
logFile.close();
}
}
std::string XNLogger::getCurrentTimeString() const {
auto now = std::chrono::system_clock::now();
auto time = std::chrono::system_clock::to_time_t(now);
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
now.time_since_epoch()) %
1000;
std::stringstream ss;
ss << std::put_time(std::localtime(&time), "%Y-%m-%d %H:%M:%S");
ss << '.' << std::setfill('0') << std::setw(3) << ms.count();
return ss.str();
}
void XNLogger::log(LogLevel level, const std::string &message) {
std::lock_guard<std::mutex> locker(mutex);
std::string logMessage = "[" + getCurrentTimeString() + "] [" +
logLevelToString(level) + "] " + message;
std::string coloredMessage;
// 根据日志等级设置颜色
switch (level) {
case Debug:
coloredMessage = COLOR_DEBUG + logMessage + COLOR_RESET;
break;
case Info:
coloredMessage = COLOR_INFO + logMessage + COLOR_RESET;
break;
case Warning:
coloredMessage = COLOR_WARNING + logMessage + COLOR_RESET;
break;
case Error:
coloredMessage = COLOR_ERROR + logMessage + COLOR_RESET;
break;
default:
coloredMessage = logMessage; // 默认无颜色
break;
}
// 控制台输出
if (consoleOutputEnabled[level]) {
if (level == Time) {
// 如果是时间日志,则不换行,回退到该行开始
std::cout << coloredMessage << "\r" << std::flush;
} else {
std::cout << coloredMessage << std::endl;
}
}
// 文件输出
if (fileOutputEnabled[level] && logFile.is_open()) {
if (level == Time) {
logFile << logMessage << "\r" << std::flush;
} else {
logFile << logMessage << std::endl;
}
}
}
void XNLogger::enableConsoleOutput(LogLevel level, bool enable) {
consoleOutputEnabled[level] = enable;
}
void XNLogger::enableFileOutput(LogLevel level, bool enable) {
fileOutputEnabled[level] = enable;
}
std::string XNLogger::logLevelToString(LogLevel level) const {
switch (level) {
case Debug:
return "DEBUG";
case Info:
return "INFO";
case Warning:
return "WARNING";
case Error:
return "ERROR";
case Time:
return "TIME";
default:
return "UNKNOWN";
}
}

248
XNCore/XNLogger/XNLogger.h Normal file
View File

@ -0,0 +1,248 @@
/**
* @file XNLogger.h
* @author jinchao
* @brief
* @version 1.0
* @date 2025-01-08
*
* @copyright Copyright (c) 2025 COMAC
*
*/
#pragma once
#include "XNCore_Function.h"
#include "XNTypeDefine.h"
#include "XNTypeTraits.h"
/**
* @brief
*/
class XNLogger {
public:
/**
* @brief
*/
enum LogLevel { Debug, Info, Warning, Error, Time };
/**
* @brief
* @return
*/
static XNLogger &instance() {
static XNLogger instance;
return instance;
}
/**
* @brief
* @param level
* @param message
*/
void log(LogLevel level, const XN_STRING &message);
/**
* @brief
* @param level
* @param enable
*/
void enableConsoleOutput(LogLevel level, XN_BOOL enable);
/**
* @brief
* @param level
* @param enable
*/
void enableFileOutput(LogLevel level, XN_BOOL enable);
private:
/**
* @brief
*/
XNLogger();
/**
* @brief
*/
~XNLogger();
/**
* @brief
*/
XNLogger(const XNLogger &) = delete;
/**
* @brief
*/
XNLogger &operator=(const XNLogger &) = delete;
/**
* @brief
*/
XN_STRING logFilePath;
/**
* @brief
*/
XN_BOOL consoleOutputEnabled[5];
/**
* @brief
*/
XN_BOOL fileOutputEnabled[5];
/**
* @brief
*/
XN_OFSTREAM logFile;
/**
* @brief
*/
XN_MUTEX mutex;
/**
* @brief
* @param level
* @return
*/
XN_STRING logLevelToString(LogLevel level) const;
/**
* @brief
* @return
*/
XN_STRING getCurrentTimeString() const;
/**
* @brief
*/
const XN_STRING COLOR_RESET = "\033[0m";
/**
* @brief
*/
const XN_STRING COLOR_DEBUG = "\033[34m"; // 蓝色
/**
* @brief
*/
const XN_STRING COLOR_INFO = "\033[32m"; // 绿色
/**
* @brief
*/
const XN_STRING COLOR_WARNING = "\033[33m"; // 黄色
/**
* @brief
*/
const XN_STRING COLOR_ERROR = "\033[31m"; // 红色
};
/**
* @brief
*/
class XNLoggerHelper {
public:
/**
* @brief
* @tparam Args
* @param level
* @param message
* @param args
*/
template <typename... Args>
inline static typename std::enable_if<(sizeof...(Args) > 0), void>::type
log(XNLogger::LogLevel level, const XN_STRING &message, Args... args) {
XN_STRING formattedMessage = formatMessage(message, args...);
XNLogger::instance().log(level, formattedMessage);
}
/**
* @brief
* @param level
* @param message
*/
inline static void log(XNLogger::LogLevel level, const XN_STRING &message) {
XNLogger::instance().log(level, message);
}
private:
/**
* @brief
* @tparam T
* @param arg
* @return
*/
template <typename T> static XN_STRING convertToString(const T &arg) {
if constexpr (XNSim::is_arithmetic_v<T>) {
return std::to_string(arg); // 处理数值类型
} else if constexpr (XNSim::is_same_v<T, XN_STRING>) {
return arg;
} else if constexpr (XNSim::is_convertible_v<T, XN_STRING>) {
return XN_STRING(arg);
} else if constexpr (XNSim::is_same_v<T, char *> ||
XNSim::is_same_v<T, const char *>) {
return XN_STRING(arg);
} else {
static_assert(XNSim::is_arithmetic_v<T> ||
XNSim::is_same_v<T, XN_STRING> ||
XNSim::is_convertible_v<T, XN_STRING> ||
XNSim::is_same_v<T, XN_CHAR *> ||
XNSim::is_same_v<T, const XN_CHAR *>,
"A01021001: 不支持的类型转换详见XNLogger.cppline 199");
}
}
/**
* @brief %1%2%3
* @tparam Args
* @param message
* @param args
* @return
*/
template <typename... Args>
static XN_STRING formatMessage(const XN_STRING &message, Args &&...args) {
static_assert(
sizeof...(Args) <= 9,
"A01021002: 单条日志参数数量超过限制详见XNLogger.cppline 216");
XN_STRING result = message;
// 使用初始化列表展开参数包
int index = 1;
// 使用lambda和std::initializer_list展开参数包
(void)std::initializer_list<int>{(
[&result, &index](const auto &value) {
XN_STRING placeholder = "%" + ToXNString(index++);
size_t pos = result.find(placeholder);
if (pos != XN_STRING::npos) {
result.replace(pos, placeholder.length(), convertToString(value));
}
}(args),
0)...};
return result;
}
};
/**
* @brief
*/
#define LOG_DEBUG(message, ...) \
XNLoggerHelper::log(XNLogger::Debug, message, ##__VA_ARGS__)
/**
* @brief
*/
#define LOG_INFO(message, ...) \
XNLoggerHelper::log(XNLogger::Info, message, ##__VA_ARGS__)
/**
* @brief
*/
#define LOG_WARNING(message, ...) \
XNLoggerHelper::log(XNLogger::Warning, message, ##__VA_ARGS__)
/**
* @brief
*/
#define LOG_ERROR(message, ...) \
XNLoggerHelper::log(XNLogger::Error, message, ##__VA_ARGS__)

View File

@ -0,0 +1,7 @@
set(XNMODELMANAGER_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/XNModelManager.h
${CMAKE_CURRENT_SOURCE_DIR}/XNModelManager_p.h
${CMAKE_CURRENT_SOURCE_DIR}/XNModelManager.cpp
)
set(XNCORE_SOURCES ${XNCORE_SOURCES} ${XNMODELMANAGER_SOURCES} PARENT_SCOPE)

View File

View File

View File

View File

@ -0,0 +1,7 @@
set(XNMODELOBJECT_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/XNModelObject.h
${CMAKE_CURRENT_SOURCE_DIR}/XNModelObject_p.h
${CMAKE_CURRENT_SOURCE_DIR}/XNModelObject.cpp
)
set(XNCORE_SOURCES ${XNCORE_SOURCES} ${XNMODELOBJECT_SOURCES} PARENT_SCOPE)

View File

View File

View File

View File

@ -1,92 +0,0 @@
/**
* @file XNObject.h
* @author jinchao
* @brief
* @version 1.0
* @date 2025-01-08
*
* @copyright Copyright (c) 2025 COMAC
*
*/
#pragma once
#include "XNCore_global.h"
#include "XNLogger.h"
struct XNObjectPrivate;
/**
* @brief
*/
class XNCORE_EXPORT XNObject : public std::enable_shared_from_this<XNObject>
{
XN_METATYPE_P(XNObject)
XN_NOCOPYABLE(XNObject)
protected:
using PrivateType = XNObjectPrivate;
/**
* @brief
*/
PrivateType *_Private_Ptr;
public:
/**
* @brief
*/
XNObject();
/**
* @brief
*/
virtual ~XNObject();
protected:
/**
* @brief
* @param p
*/
XNObject(PrivateType *p);
public:
/**
* @brief ID
* @return ID
*/
uint32_t GetUniqueId();
/**
* @brief ID
* @param uniqueId ID
*/
void SetUniqueId(const uint32_t &uniqueId);
/**
* @brief
* @return
*/
const std::string &GetObjectName();
/**
* @brief
* @param name
*/
void SetObjectName(const std::string &name);
};
class XNFramework;
class XNDDSManager;
class XNEventManager;
class XNModelManager;
class XNScenarioManager;
class XNServiceManager;
class XNThreadManager;
class XNTimeManager;
XNCLASS_PTR_DECLARE(XNFramework)
XNCLASS_PTR_DECLARE(XNDDSManager)
XNCLASS_PTR_DECLARE(XNEventManager)
XNCLASS_PTR_DECLARE(XNModelManager)
XNCLASS_PTR_DECLARE(XNScenarioManager)
XNCLASS_PTR_DECLARE(XNServiceManager)
XNCLASS_PTR_DECLARE(XNThreadManager)
XNCLASS_PTR_DECLARE(XNTimeManager)

View File

@ -0,0 +1,7 @@
set(XNOBJECT_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/XNObject.h
${CMAKE_CURRENT_SOURCE_DIR}/XNObject_p.h
${CMAKE_CURRENT_SOURCE_DIR}/XNObject.cpp
)
set(XNCORE_SOURCES ${XNCORE_SOURCES} ${XNOBJECT_SOURCES} PARENT_SCOPE)

90
XNCore/XNObject.cpp → XNCore/XNObject/XNObject.cpp Executable file → Normal file
View File

@ -1,45 +1,45 @@
#include "XNObject.h"
#include "XNObject_p.h"
XNObject::XNObject() : _Private_Ptr(new XNObjectPrivate())
{
_Private_Ptr->_Public_Ptr = this;
}
XNObject::XNObject(PrivateType *p) : _Private_Ptr(p)
{
_Private_Ptr->_Public_Ptr = this;
}
XNObject::~XNObject()
{
if (_Private_Ptr) {
delete _Private_Ptr;
}
_Private_Ptr = nullptr;
}
XNObjectPrivate::~XNObjectPrivate()
{
_Public_Ptr = nullptr;
}
uint32_t XNObject::GetUniqueId()
{
return _Private_Ptr->uUniqueID;
}
void XNObject::SetUniqueId(const uint32_t &uniqueId)
{
_Private_Ptr->uUniqueID = uniqueId;
}
const std::string &XNObject::GetObjectName()
{
return _Private_Ptr->sObjectName;
}
void XNObject::SetObjectName(const std::string &name)
{
_Private_Ptr->sObjectName = name;
}
#include "XNObject.h"
#include "XNObject_p.h"
XNObject::XNObject() : _Private_Ptr(new XNObjectPrivate())
{
_Private_Ptr->_Public_Ptr = this;
}
XNObject::XNObject(PrivateType *p) : _Private_Ptr(p)
{
_Private_Ptr->_Public_Ptr = this;
}
XNObject::~XNObject()
{
if (_Private_Ptr) {
delete _Private_Ptr;
}
_Private_Ptr = nullptr;
}
XNObjectPrivate::~XNObjectPrivate()
{
_Public_Ptr = nullptr;
}
uint32_t XNObject::GetUniqueId()
{
return _Private_Ptr->uUniqueID;
}
void XNObject::SetUniqueId(const uint32_t &uniqueId)
{
_Private_Ptr->uUniqueID = uniqueId;
}
const std::string &XNObject::GetObjectName()
{
return _Private_Ptr->sObjectName;
}
void XNObject::SetObjectName(const std::string &name)
{
_Private_Ptr->sObjectName = name;
}

View File

@ -0,0 +1,91 @@
/**
* @file XNObject.h
* @author jinchao
* @brief
* @version 1.0
* @date 2025-01-08
*
* @copyright Copyright (c) 2025 COMAC
*
*/
#pragma once
#include "XNCore_global.h"
#include "XNLogger.h"
struct XNObjectPrivate;
/**
* @brief
*/
class XNCORE_EXPORT XNObject : public std::enable_shared_from_this<XNObject> {
XN_METATYPE_P(XNObject)
XN_NOCOPYABLE(XNObject)
protected:
using PrivateType = XNObjectPrivate;
/**
* @brief
*/
PrivateType *_Private_Ptr;
public:
/**
* @brief
*/
XNObject();
/**
* @brief
*/
virtual ~XNObject();
protected:
/**
* @brief
* @param p
*/
XNObject(PrivateType *p);
public:
/**
* @brief ID
* @return ID
*/
uint32_t GetUniqueId();
/**
* @brief ID
* @param uniqueId ID
*/
void SetUniqueId(const uint32_t &uniqueId);
/**
* @brief
* @return
*/
const std::string &GetObjectName();
/**
* @brief
* @param name
*/
void SetObjectName(const std::string &name);
};
class XNFramework;
class XNDDSManager;
class XNEventManager;
class XNModelManager;
class XNScenarioManager;
class XNServiceManager;
class XNThreadManager;
class XNTimeManager;
XNCLASS_PTR_DECLARE(XNFramework)
XNCLASS_PTR_DECLARE(XNDDSManager)
XNCLASS_PTR_DECLARE(XNEventManager)
XNCLASS_PTR_DECLARE(XNModelManager)
XNCLASS_PTR_DECLARE(XNScenarioManager)
XNCLASS_PTR_DECLARE(XNServiceManager)
XNCLASS_PTR_DECLARE(XNThreadManager)
XNCLASS_PTR_DECLARE(XNTimeManager)

68
XNCore/XNObject_p.h → XNCore/XNObject/XNObject_p.h Executable file → Normal file
View File

@ -1,34 +1,34 @@
/**
* @file XNObject_p.h
* @author jinchao
* @brief
* @version 1.0
* @date 2025-01-08
*
* @copyright Copyright (c) 2025 COMAC
*
*/
#pragma once
#include "XNObject.h"
/**
* @brief
*/
struct XNObjectPrivate {
virtual ~XNObjectPrivate();
/**
* @brief
*/
XNObject *_Public_Ptr;
/**
* @brief ID
*/
uint32_t uUniqueID;
/**
* @brief
*/
std::string sObjectName;
};
/**
* @file XNObject_p.h
* @author jinchao
* @brief
* @version 1.0
* @date 2025-01-08
*
* @copyright Copyright (c) 2025 COMAC
*
*/
#pragma once
#include "XNObject.h"
/**
* @brief
*/
struct XNObjectPrivate {
virtual ~XNObjectPrivate();
/**
* @brief
*/
XNObject *_Public_Ptr;
/**
* @brief ID
*/
uint32_t uUniqueID;
/**
* @brief
*/
std::string sObjectName;
};

View File

@ -0,0 +1,7 @@
set(XNSCENARIOMANAGER_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/XNScenarioManager.h
${CMAKE_CURRENT_SOURCE_DIR}/XNScenarioManager_p.h
${CMAKE_CURRENT_SOURCE_DIR}/XNScenarioManager.cpp
)
set(XNCORE_SOURCES ${XNCORE_SOURCES} ${XNSCENARIOMANAGER_SOURCES} PARENT_SCOPE)

View File

@ -0,0 +1,7 @@
set(XNSERVICEMANAGER_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/XNServiceManager.h
${CMAKE_CURRENT_SOURCE_DIR}/XNServiceManager_p.h
${CMAKE_CURRENT_SOURCE_DIR}/XNServiceManager.cpp
)
set(XNCORE_SOURCES ${XNCORE_SOURCES} ${XNSERVICEMANAGER_SOURCES} PARENT_SCOPE)

View File

@ -0,0 +1,7 @@
set(XNSERVICEOBJECT_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/XNServiceObject.h
${CMAKE_CURRENT_SOURCE_DIR}/XNServiceObject_p.h
${CMAKE_CURRENT_SOURCE_DIR}/XNServiceObject.cpp
)
set(XNCORE_SOURCES ${XNCORE_SOURCES} ${XNSERVICEOBJECT_SOURCES} PARENT_SCOPE)

View File

View File

@ -0,0 +1,7 @@
set(XNTHREADMANAGER_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/XNThreadManager.h
${CMAKE_CURRENT_SOURCE_DIR}/XNThreadManager_p.h
${CMAKE_CURRENT_SOURCE_DIR}/XNThreadManager.cpp
)
set(XNCORE_SOURCES ${XNCORE_SOURCES} ${XNTHREADMANAGER_SOURCES} PARENT_SCOPE)

View File

View File

@ -0,0 +1,7 @@
set(XNTHREADOBJECT_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/XNThreadObject.h
${CMAKE_CURRENT_SOURCE_DIR}/XNThreadObject_p.h
${CMAKE_CURRENT_SOURCE_DIR}/XNThreadObject.cpp
)
set(XNCORE_SOURCES ${XNCORE_SOURCES} ${XNTHREADOBJECT_SOURCES} PARENT_SCOPE)

View File

View File

View File

@ -0,0 +1,7 @@
set(XNTIMEMANAGER_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/XNTimeManager.h
${CMAKE_CURRENT_SOURCE_DIR}/XNTimeManager_p.h
${CMAKE_CURRENT_SOURCE_DIR}/XNTimeManager.cpp
)
set(XNCORE_SOURCES ${XNCORE_SOURCES} ${XNTIMEMANAGER_SOURCES} PARENT_SCOPE)

View File

View File

View File

View File

@ -1,45 +0,0 @@
#pragma once
#include <array>
#include <type_traits>
#include <cstddef>
template <typename T>
struct is_std_array : std::false_type {
};
template <typename T, std::size_t N>
struct is_std_array<std::array<T, N>> : std::true_type {
};
// 变量模板简化使用
template <typename T>
inline constexpr bool is_std_array_v = is_std_array<T>::value;
/**
* @brief
* @tparam T
* @return std::array1
*/
template <typename T>
struct array_size : std::integral_constant<std::size_t, 1> {
};
template <typename T, std::size_t N>
struct array_size<std::array<T, N>> : std::integral_constant<std::size_t, N> {
};
// 变量模板简化使用
template <typename T>
inline constexpr std::size_t array_size_v = array_size<T>::value;
// 获取类型大小的辅助函数
template <typename T>
constexpr size_t getTypeSize()
{
if constexpr (is_std_array_v<T>) {
// 对于std::array计算所有元素的总大小
return getTypeSize<typename T::value_type>() * array_size_v<T>;
} else {
return sizeof(T);
}
}