先移除了DDS接口的Qt依赖

This commit is contained in:
jinchao 2025-05-19 09:49:54 +08:00
parent d92947628b
commit fc315a882c
3 changed files with 310 additions and 201 deletions

View File

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

View File

@ -75,6 +75,9 @@
"complex": "cpp", "complex": "cpp",
"set": "cpp", "set": "cpp",
"regex": "cpp", "regex": "cpp",
"qlibrary": "cpp" "qlibrary": "cpp",
"csignal": "cpp",
"any": "cpp",
"unordered_set": "cpp"
} }
} }

View File

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