diff --git a/Release/include/XNCore/XNDDSInterface.h b/Release/include/XNCore/XNDDSInterface.h index 61c294f..5b1f610 100644 --- a/Release/include/XNCore/XNDDSInterface.h +++ b/Release/include/XNCore/XNDDSInterface.h @@ -1,7 +1,20 @@ #pragma once -#include "XNObject.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include + +// 定义UDP包的最大大小 +constexpr size_t MAX_UDP_PACKET_SIZE = 40000; + template struct is_std_array : std::false_type { }; @@ -14,175 +27,215 @@ struct is_std_array> : std::true_type { template inline constexpr bool is_std_array_v = is_std_array::value; -class XNDDSInterface : public XNObject +// 获取类型大小的辅助函数 +template +constexpr size_t getTypeSize() +{ + if constexpr (is_std_array_v) { + // 对于std::array,计算所有元素的总大小 + return getTypeSize() * std::tuple_size::value; + } else { + return sizeof(T); + } +} + +class XNDDSInterface { - Q_OBJECT public: - explicit XNDDSInterface(QObject *parent = nullptr) : XNObject(parent) {} - virtual ~XNDDSInterface() {} + XNDDSInterface() = default; + virtual ~XNDDSInterface() = default; template - QByteArray getQByteArray(eprosima::fastcdr::optional data) + void getByteArray(eprosima::fastcdr::optional data, uint8_t *buffer, size_t bufferSize) { - QByteArray value; - // 如果T是普通类型,将data中的数据转换为QByteArray + if (bufferSize < getTypeSize()) + return; + if constexpr (std::is_arithmetic_v) { - QDataStream dataStream(&value, QIODevice::WriteOnly); - dataStream.setByteOrder(QDataStream::LittleEndian); if (data) { - dataStream << data.value(); + std::memcpy(buffer, &data.value(), sizeof(T)); } else { - dataStream << (T)0; + T zero = 0; + std::memcpy(buffer, &zero, sizeof(T)); } - } - // 如果T是std::array,则需要根据T的类型和大小,生成一个std::array的QByteArray - else if constexpr (is_std_array_v) { + } else if constexpr (is_std_array_v) { if (data) { - value = getQByteArrayFromStdArray(data.value()); + getByteArrayFromStdArray(data.value(), buffer, bufferSize); } else { T zero = {}; - value = getQByteArrayFromStdArray(zero); + getByteArrayFromStdArray(zero, buffer, bufferSize); } } - return value; } template - QByteArray getQByteArrayFromStdArray(std::array data) + void getByteArrayFromStdArray(std::array data, uint8_t *buffer, size_t bufferSize) { - QByteArray value; - QDataStream dataStream(&value, QIODevice::WriteOnly); - dataStream.setByteOrder(QDataStream::LittleEndian); + if (bufferSize < getTypeSize() * N) + return; + for (std::size_t i = 0; i < N; ++i) { if constexpr (std::is_arithmetic_v) { - dataStream << data[i]; + std::memcpy(buffer + i * getTypeSize(), &data[i], getTypeSize()); } else { - dataStream << getQByteArrayFromStdArray(data[i]); + getByteArrayFromStdArray(data[i], buffer + i * getTypeSize(), getTypeSize()); } } - return value; } - QByteArray getUDPPackage() + void getUDPPackage(uint8_t *buffer, size_t bufferSize) { - QByteArray package; - QByteArray header = this->header.mid(0, 5); - package.append(header); - for (auto func : getByteArrayFunction) { - package.append(func()); + if (bufferSize < MAX_UDP_PACKET_SIZE) + return; + + size_t currentPos = 0; + + // 复制头部 + if (headerSize >= 5) { + std::memcpy(buffer, header, 5); + currentPos = 5; + } + + // 复制数据 + for (auto func : getByteArrayFunction) { + if (currentPos + func.size <= MAX_UDP_PACKET_SIZE) { + func.func(buffer + currentPos, func.size); + currentPos += func.size; + } else { + break; // 超出最大包大小 + } + } + + // 更新包大小 + if (currentPos >= 5) { + buffer[4] = static_cast(currentPos); } - package[4] = package.size(); - return package; } template - QString getQString(eprosima::fastcdr::optional data) + std::string getString(eprosima::fastcdr::optional data) { if constexpr (std::is_arithmetic_v) { if (data) { - return QString::number(data.value()); + return std::to_string(data.value()); } else { - return QString::number(0); + return std::to_string(0); } } else if constexpr (std::is_same_v) { if (data) { - return getQStringFromStdArray(data.value()); + return getStringFromStdArray(data.value()); } else { T zero = {}; - return getQStringFromStdArray(zero); + return getStringFromStdArray(zero); } } - return QString(); + return std::string(); } template - QString getQStringFromStdArray(std::array data) + std::string getStringFromStdArray(std::array data) { - QStringList list; + std::stringstream ss; for (std::size_t i = 0; i < N; ++i) { + if (i > 0) + ss << ","; if constexpr (std::is_arithmetic_v) { - list.append(QString::number(data[i])); + ss << data[i]; } else { - list.append(getQStringFromStdArray(data[i])); + ss << getStringFromStdArray(data[i]); } } - return list.join(","); + return ss.str(); } - QString getData(const QString &varName) + std::string getData(const std::string &varName) { - int index1 = -1; - int index2 = -1; - QString trueVarName = varName; - // 检查变量名中是否存在数组标记 - if (varName.contains('[')) { - // 解析数组索引 - int startPos = varName.indexOf('['); - int midPos = varName.indexOf("]["); - int endPos = varName.lastIndexOf(']'); + int index1 = -1; + int index2 = -1; + std::string trueVarName = varName; - // 如果是二维数组 (格式: name[index1][index2]) - if (midPos != -1) { - bool ok1 = false, ok2 = false; - index1 = varName.mid(startPos + 1, midPos - startPos - 1).toInt(&ok1); - index2 = varName.mid(midPos + 2, endPos - midPos - 2).toInt(&ok2); + size_t startPos = varName.find('['); + if (startPos != std::string::npos) { + size_t midPos = varName.find("][", startPos); + size_t endPos = varName.find_last_of(']'); - if (!ok1 || !ok2) { - qWarning() << "无法解析数组索引:" << varName; + if (midPos != std::string::npos) { + try { + index1 = std::stoi(varName.substr(startPos + 1, midPos - startPos - 1)); + index2 = std::stoi(varName.substr(midPos + 2, endPos - midPos - 2)); + } catch (...) { + std::cerr << "无法解析数组索引: " << varName << std::endl; index1 = 0; index2 = 0; } - } - // 如果是一维数组 (格式: name[index1]) - else if (startPos != -1 && endPos != -1) { - bool ok = false; - index1 = varName.mid(startPos + 1, endPos - startPos - 1).toInt(&ok); - - if (!ok) { - qWarning() << "无法解析数组索引:" << varName; + } else if (endPos != std::string::npos) { + try { + index1 = std::stoi(varName.substr(startPos + 1, endPos - startPos - 1)); + } catch (...) { + std::cerr << "无法解析数组索引: " << varName << std::endl; index1 = 0; } } - trueVarName = varName.left(startPos); + trueVarName = varName.substr(0, startPos); } + auto it = getDataFunction.find(trueVarName); if (it == getDataFunction.end()) { - return QString(); // 返回空字符串表示未找到 + return std::string(); } + + std::lock_guard lock(mutex); + std::string result = it->second(); + if (index1 < 0) { - QMutexLocker locker(&mutex); - return it.value()(); - } else if (index2 < 0) { - QMutexLocker locker(&mutex); - QStringList list = it.value()().split(","); - if (index1 >= list.size()) { - qWarning() << "数组索引超出范围:" << varName; - return QString(); - } - return list[index1]; - } else { - QMutexLocker locker(&mutex); - QStringList list = it.value()().split(","); - if (index1 >= list.size()) { - qWarning() << "数组索引超出范围:" << varName; - return QString(); - } - QStringList list2 = list[index1].split(" "); - if (index2 >= list2.size()) { - qWarning() << "数组索引超出范围:" << varName; - return QString(); - } - return list2[index2]; + return result; } + + std::vector list; + std::stringstream ss(result); + std::string item; + while (std::getline(ss, item, ',')) { + list.push_back(item); + } + + if (index1 >= static_cast(list.size())) { + std::cerr << "数组索引超出范围: " << varName << std::endl; + return std::string(); + } + + if (index2 < 0) { + return list[index1]; + } + + std::vector list2; + std::stringstream ss2(list[index1]); + while (std::getline(ss2, item, ' ')) { + list2.push_back(item); + } + + if (index2 >= static_cast(list2.size())) { + std::cerr << "数组索引超出范围: " << varName << std::endl; + return std::string(); + } + + return list2[index2]; } protected: - QHash> getDataFunction; - QVector> getByteArrayFunction; - QMutex mutex; - QByteArray header; + struct ByteArrayFunc { + std::function func; + size_t size; + }; + + std::unordered_map> getDataFunction; + std::vector getByteArrayFunction; + std::mutex mutex; + uint8_t header[5]{}; // 固定大小的头部 + size_t headerSize = 0; }; #define MAP_GET_DATA_FUNC(NAME) \ - getDataFunction[#NAME] = [this]() { return getQString(data.NAME()); }; \ - getByteArrayFunction.push_back([this]() { return getQByteArray(data.NAME()); }) + getDataFunction[#NAME] = [this]() { return getString(data.NAME()); }; \ + getByteArrayFunction.push_back( \ + {[this](uint8_t *buffer, size_t size) { getByteArray(data.NAME(), buffer, size); }, \ + getTypeSize()}) diff --git a/XNCore/.vscode/settings.json b/XNCore/.vscode/settings.json index 01bfe6d..2bc15f4 100755 --- a/XNCore/.vscode/settings.json +++ b/XNCore/.vscode/settings.json @@ -75,6 +75,9 @@ "complex": "cpp", "set": "cpp", "regex": "cpp", - "qlibrary": "cpp" + "qlibrary": "cpp", + "csignal": "cpp", + "any": "cpp", + "unordered_set": "cpp" } } \ No newline at end of file diff --git a/XNCore/XNDDSInterface.h b/XNCore/XNDDSInterface.h index 61c294f..5b1f610 100755 --- a/XNCore/XNDDSInterface.h +++ b/XNCore/XNDDSInterface.h @@ -1,7 +1,20 @@ #pragma once -#include "XNObject.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include + +// 定义UDP包的最大大小 +constexpr size_t MAX_UDP_PACKET_SIZE = 40000; + template struct is_std_array : std::false_type { }; @@ -14,175 +27,215 @@ struct is_std_array> : std::true_type { template inline constexpr bool is_std_array_v = is_std_array::value; -class XNDDSInterface : public XNObject +// 获取类型大小的辅助函数 +template +constexpr size_t getTypeSize() +{ + if constexpr (is_std_array_v) { + // 对于std::array,计算所有元素的总大小 + return getTypeSize() * std::tuple_size::value; + } else { + return sizeof(T); + } +} + +class XNDDSInterface { - Q_OBJECT public: - explicit XNDDSInterface(QObject *parent = nullptr) : XNObject(parent) {} - virtual ~XNDDSInterface() {} + XNDDSInterface() = default; + virtual ~XNDDSInterface() = default; template - QByteArray getQByteArray(eprosima::fastcdr::optional data) + void getByteArray(eprosima::fastcdr::optional data, uint8_t *buffer, size_t bufferSize) { - QByteArray value; - // 如果T是普通类型,将data中的数据转换为QByteArray + if (bufferSize < getTypeSize()) + return; + if constexpr (std::is_arithmetic_v) { - QDataStream dataStream(&value, QIODevice::WriteOnly); - dataStream.setByteOrder(QDataStream::LittleEndian); if (data) { - dataStream << data.value(); + std::memcpy(buffer, &data.value(), sizeof(T)); } else { - dataStream << (T)0; + T zero = 0; + std::memcpy(buffer, &zero, sizeof(T)); } - } - // 如果T是std::array,则需要根据T的类型和大小,生成一个std::array的QByteArray - else if constexpr (is_std_array_v) { + } else if constexpr (is_std_array_v) { if (data) { - value = getQByteArrayFromStdArray(data.value()); + getByteArrayFromStdArray(data.value(), buffer, bufferSize); } else { T zero = {}; - value = getQByteArrayFromStdArray(zero); + getByteArrayFromStdArray(zero, buffer, bufferSize); } } - return value; } template - QByteArray getQByteArrayFromStdArray(std::array data) + void getByteArrayFromStdArray(std::array data, uint8_t *buffer, size_t bufferSize) { - QByteArray value; - QDataStream dataStream(&value, QIODevice::WriteOnly); - dataStream.setByteOrder(QDataStream::LittleEndian); + if (bufferSize < getTypeSize() * N) + return; + for (std::size_t i = 0; i < N; ++i) { if constexpr (std::is_arithmetic_v) { - dataStream << data[i]; + std::memcpy(buffer + i * getTypeSize(), &data[i], getTypeSize()); } else { - dataStream << getQByteArrayFromStdArray(data[i]); + getByteArrayFromStdArray(data[i], buffer + i * getTypeSize(), getTypeSize()); } } - return value; } - QByteArray getUDPPackage() + void getUDPPackage(uint8_t *buffer, size_t bufferSize) { - QByteArray package; - QByteArray header = this->header.mid(0, 5); - package.append(header); - for (auto func : getByteArrayFunction) { - package.append(func()); + if (bufferSize < MAX_UDP_PACKET_SIZE) + return; + + size_t currentPos = 0; + + // 复制头部 + if (headerSize >= 5) { + std::memcpy(buffer, header, 5); + currentPos = 5; + } + + // 复制数据 + for (auto func : getByteArrayFunction) { + if (currentPos + func.size <= MAX_UDP_PACKET_SIZE) { + func.func(buffer + currentPos, func.size); + currentPos += func.size; + } else { + break; // 超出最大包大小 + } + } + + // 更新包大小 + if (currentPos >= 5) { + buffer[4] = static_cast(currentPos); } - package[4] = package.size(); - return package; } template - QString getQString(eprosima::fastcdr::optional data) + std::string getString(eprosima::fastcdr::optional data) { if constexpr (std::is_arithmetic_v) { if (data) { - return QString::number(data.value()); + return std::to_string(data.value()); } else { - return QString::number(0); + return std::to_string(0); } } else if constexpr (std::is_same_v) { if (data) { - return getQStringFromStdArray(data.value()); + return getStringFromStdArray(data.value()); } else { T zero = {}; - return getQStringFromStdArray(zero); + return getStringFromStdArray(zero); } } - return QString(); + return std::string(); } template - QString getQStringFromStdArray(std::array data) + std::string getStringFromStdArray(std::array data) { - QStringList list; + std::stringstream ss; for (std::size_t i = 0; i < N; ++i) { + if (i > 0) + ss << ","; if constexpr (std::is_arithmetic_v) { - list.append(QString::number(data[i])); + ss << data[i]; } else { - list.append(getQStringFromStdArray(data[i])); + ss << getStringFromStdArray(data[i]); } } - return list.join(","); + return ss.str(); } - QString getData(const QString &varName) + std::string getData(const std::string &varName) { - int index1 = -1; - int index2 = -1; - QString trueVarName = varName; - // 检查变量名中是否存在数组标记 - if (varName.contains('[')) { - // 解析数组索引 - int startPos = varName.indexOf('['); - int midPos = varName.indexOf("]["); - int endPos = varName.lastIndexOf(']'); + int index1 = -1; + int index2 = -1; + std::string trueVarName = varName; - // 如果是二维数组 (格式: name[index1][index2]) - if (midPos != -1) { - bool ok1 = false, ok2 = false; - index1 = varName.mid(startPos + 1, midPos - startPos - 1).toInt(&ok1); - index2 = varName.mid(midPos + 2, endPos - midPos - 2).toInt(&ok2); + size_t startPos = varName.find('['); + if (startPos != std::string::npos) { + size_t midPos = varName.find("][", startPos); + size_t endPos = varName.find_last_of(']'); - if (!ok1 || !ok2) { - qWarning() << "无法解析数组索引:" << varName; + if (midPos != std::string::npos) { + try { + index1 = std::stoi(varName.substr(startPos + 1, midPos - startPos - 1)); + index2 = std::stoi(varName.substr(midPos + 2, endPos - midPos - 2)); + } catch (...) { + std::cerr << "无法解析数组索引: " << varName << std::endl; index1 = 0; index2 = 0; } - } - // 如果是一维数组 (格式: name[index1]) - else if (startPos != -1 && endPos != -1) { - bool ok = false; - index1 = varName.mid(startPos + 1, endPos - startPos - 1).toInt(&ok); - - if (!ok) { - qWarning() << "无法解析数组索引:" << varName; + } else if (endPos != std::string::npos) { + try { + index1 = std::stoi(varName.substr(startPos + 1, endPos - startPos - 1)); + } catch (...) { + std::cerr << "无法解析数组索引: " << varName << std::endl; index1 = 0; } } - trueVarName = varName.left(startPos); + trueVarName = varName.substr(0, startPos); } + auto it = getDataFunction.find(trueVarName); if (it == getDataFunction.end()) { - return QString(); // 返回空字符串表示未找到 + return std::string(); } + + std::lock_guard lock(mutex); + std::string result = it->second(); + if (index1 < 0) { - QMutexLocker locker(&mutex); - return it.value()(); - } else if (index2 < 0) { - QMutexLocker locker(&mutex); - QStringList list = it.value()().split(","); - if (index1 >= list.size()) { - qWarning() << "数组索引超出范围:" << varName; - return QString(); - } - return list[index1]; - } else { - QMutexLocker locker(&mutex); - QStringList list = it.value()().split(","); - if (index1 >= list.size()) { - qWarning() << "数组索引超出范围:" << varName; - return QString(); - } - QStringList list2 = list[index1].split(" "); - if (index2 >= list2.size()) { - qWarning() << "数组索引超出范围:" << varName; - return QString(); - } - return list2[index2]; + return result; } + + std::vector list; + std::stringstream ss(result); + std::string item; + while (std::getline(ss, item, ',')) { + list.push_back(item); + } + + if (index1 >= static_cast(list.size())) { + std::cerr << "数组索引超出范围: " << varName << std::endl; + return std::string(); + } + + if (index2 < 0) { + return list[index1]; + } + + std::vector list2; + std::stringstream ss2(list[index1]); + while (std::getline(ss2, item, ' ')) { + list2.push_back(item); + } + + if (index2 >= static_cast(list2.size())) { + std::cerr << "数组索引超出范围: " << varName << std::endl; + return std::string(); + } + + return list2[index2]; } protected: - QHash> getDataFunction; - QVector> getByteArrayFunction; - QMutex mutex; - QByteArray header; + struct ByteArrayFunc { + std::function func; + size_t size; + }; + + std::unordered_map> getDataFunction; + std::vector getByteArrayFunction; + std::mutex mutex; + uint8_t header[5]{}; // 固定大小的头部 + size_t headerSize = 0; }; #define MAP_GET_DATA_FUNC(NAME) \ - getDataFunction[#NAME] = [this]() { return getQString(data.NAME()); }; \ - getByteArrayFunction.push_back([this]() { return getQByteArray(data.NAME()); }) + getDataFunction[#NAME] = [this]() { return getString(data.NAME()); }; \ + getByteArrayFunction.push_back( \ + {[this](uint8_t *buffer, size_t size) { getByteArray(data.NAME(), buffer, size); }, \ + getTypeSize()})