2025-05-26 09:04:11 +08:00
|
|
|
#include "DDSInterfaceGen.h"
|
|
|
|
|
|
|
|
DDSInterfaceGen::DDSInterfaceGen(const std::string &idlPath)
|
|
|
|
{
|
|
|
|
IDLPath = fs::path(idlPath).parent_path().string();
|
|
|
|
IDLName = fs::path(idlPath).stem().string();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DDSInterfaceGen::generateDDSInterface(const AllInterfaceData &interfaceData)
|
|
|
|
{
|
|
|
|
std::string systemName = interfaceData.systemName;
|
|
|
|
std::string planeName = interfaceData.planeName;
|
|
|
|
|
|
|
|
for (const auto &ata : interfaceData.ataInterfaceData) {
|
|
|
|
std::string ataName = ata.ataName;
|
|
|
|
std::string interfaceFolderPath = IDLPath + "/" + ataName;
|
|
|
|
fs::create_directories(interfaceFolderPath);
|
|
|
|
std::string nameSpace = systemName + "::" + planeName + "::" + ataName;
|
|
|
|
for (const auto &structData : ata.structInterfaceData) {
|
|
|
|
std::string structName = structData.modelStructName;
|
|
|
|
generateDDSInterfaceHpp(nameSpace, structName, interfaceFolderPath,
|
|
|
|
structData.interfaceData);
|
|
|
|
generateDDSInterfaceCxx(nameSpace, structName, interfaceFolderPath,
|
|
|
|
structData.interfaceData);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DDSInterfaceGen::generateDDSInterfaceHpp(const std::string &nameSpace,
|
|
|
|
const std::string &structName,
|
|
|
|
const std::string &interfaceFolderPath,
|
|
|
|
const std::vector<InterfaceData> &interfaceData)
|
|
|
|
{
|
|
|
|
std::string className = structName + "_Interface";
|
|
|
|
std::string topicType = nameSpace + "::" + structName;
|
|
|
|
std::string hppFilePath = interfaceFolderPath + "/" + structName + ".hpp";
|
|
|
|
std::ofstream hppFile(hppFilePath);
|
|
|
|
// 1. 写入引用头文件
|
|
|
|
hppFile << "#pragma once" << std::endl;
|
|
|
|
hppFile << "#include \"../" << IDLName << "PubSubTypes.hpp\"" << std::endl;
|
|
|
|
hppFile << "#include \"XNCore/XNDDSInterface.h\"" << std::endl;
|
|
|
|
// 2. 写入命名空间
|
|
|
|
hppFile << "namespace " << nameSpace << std::endl;
|
|
|
|
hppFile << "{" << std::endl;
|
|
|
|
// 3. 写入类声明
|
2025-05-30 14:16:16 +08:00
|
|
|
hppFile << "class " << className << " : public XNDDSInterface" << std::endl;
|
2025-05-26 09:04:11 +08:00
|
|
|
hppFile << "{" << std::endl;
|
|
|
|
hppFile << "public:" << std::endl;
|
2025-05-30 14:16:16 +08:00
|
|
|
hppFile << "\t" << "using DDSType = " << topicType << ";" << std::endl;
|
|
|
|
hppFile << "\t" << "using DDSPubSubType = " << topicType << "PubSubType;" << std::endl;
|
|
|
|
hppFile << "\t" << "static const std::string topic_name;" << std::endl;
|
2025-05-26 09:04:11 +08:00
|
|
|
// 4. 写入构造函数和析构函数
|
|
|
|
hppFile << "\t" << className << "();" << std::endl;
|
|
|
|
hppFile << "\t" << "virtual ~" << className << "();" << std::endl;
|
|
|
|
// 5. 写入初始化函数
|
|
|
|
hppFile << "\t"
|
|
|
|
<< "virtual void Initialize(XNFrameworkPtr framework, uint32_t modelId, uint32_t "
|
|
|
|
"DDS_type) override;"
|
|
|
|
<< std::endl;
|
|
|
|
// 6. 写入清空数据函数
|
|
|
|
hppFile << "\t" << "virtual void clearOutData() override;" << std::endl;
|
|
|
|
// 7. 写入发送数据函数
|
|
|
|
hppFile << "\t" << "virtual void sendOutData() override;" << std::endl;
|
|
|
|
// 8. 写入输入数据监听函数
|
|
|
|
hppFile << "\t" << "void inputDataListener(const " << topicType << " &input);" << std::endl;
|
|
|
|
// 9. 写入获取数据模板函数
|
|
|
|
hppFile << "\t" << "template <typename T>" << std::endl;
|
|
|
|
hppFile << "\t" << "void getData(T *model_data)" << std::endl;
|
|
|
|
hppFile << "\t" << "{" << std::endl;
|
2025-05-26 15:27:02 +08:00
|
|
|
hppFile << "\t\t" << "std::lock_guard<std::mutex> lock(dataMutex);" << std::endl;
|
2025-05-26 09:04:11 +08:00
|
|
|
hppFile << "\t\t" << "if(model_data == nullptr)" << std::endl;
|
|
|
|
hppFile << "\t\t\t" << "return;" << std::endl;
|
|
|
|
for (const auto &interface : interfaceData) {
|
|
|
|
hppFile << "\t\t" << "assign_value_get(data." << interface.interfaceName
|
|
|
|
<< "(), model_data->" << interface.interfaceName << ");" << std::endl;
|
|
|
|
}
|
|
|
|
hppFile << "\t" << "}" << std::endl;
|
|
|
|
// 10. 写入设置数据模板函数
|
|
|
|
hppFile << "\t" << "template <typename T>" << std::endl;
|
|
|
|
hppFile << "\t" << "void setData(T *model_data)" << std::endl;
|
|
|
|
hppFile << "\t" << "{" << std::endl;
|
|
|
|
hppFile << "\t\t" << "if(model_data == nullptr)" << std::endl;
|
|
|
|
hppFile << "\t\t\t" << "return;" << std::endl;
|
2025-05-26 15:27:02 +08:00
|
|
|
hppFile << "\t\t" << "std::lock_guard<std::mutex> lock(outDataMutex);" << std::endl;
|
2025-05-26 09:04:11 +08:00
|
|
|
hppFile << "\t\t" << "clearOutData();" << std::endl;
|
|
|
|
for (const auto &interface : interfaceData) {
|
2025-06-06 11:02:12 +08:00
|
|
|
hppFile << "\t\t" << "assign_value_set(out_data." << interface.interfaceName
|
2025-05-26 15:27:02 +08:00
|
|
|
<< "(), model_data->" << interface.interfaceName << ");" << std::endl;
|
2025-05-26 09:04:11 +08:00
|
|
|
}
|
2025-06-06 11:02:12 +08:00
|
|
|
hppFile << "\t\t" << "sendOutData();" << std::endl;
|
2025-05-26 09:04:11 +08:00
|
|
|
hppFile << "\t" << "}" << std::endl;
|
|
|
|
// 11. 写入私有成员变量
|
2025-05-30 14:16:16 +08:00
|
|
|
hppFile << "" << "protected:" << std::endl;
|
|
|
|
hppFile << "\t" << "DDSType data;" << std::endl;
|
|
|
|
hppFile << "\t" << "DDSType out_data;" << std::endl;
|
2025-05-26 09:04:11 +08:00
|
|
|
// 12. 写入类声明结束
|
|
|
|
hppFile << "};" << std::endl;
|
|
|
|
// 13. 写入命名空间结束
|
|
|
|
hppFile << "}" << std::endl;
|
|
|
|
hppFile.close();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DDSInterfaceGen::generateDDSInterfaceCxx(const std::string &nameSpace,
|
|
|
|
const std::string &structName,
|
|
|
|
const std::string &interfaceFolderPath,
|
|
|
|
const std::vector<InterfaceData> &interfaceData)
|
|
|
|
{
|
|
|
|
std::string className = structName + "_Interface";
|
|
|
|
std::string topicType = nameSpace + "::" + structName;
|
|
|
|
std::string cxxFilePath = interfaceFolderPath + "/" + structName + ".cxx";
|
|
|
|
std::ofstream cxxFile(cxxFilePath);
|
|
|
|
// 1. 写入引用头文件
|
|
|
|
cxxFile << "#include \"" << structName << ".hpp\"" << std::endl;
|
|
|
|
// 2. 写入命名空间
|
2025-05-30 14:16:16 +08:00
|
|
|
cxxFile << "const std::string " << nameSpace << "::" << className << "::topic_name = \""
|
|
|
|
<< topicType << "\";" << std::endl;
|
2025-05-26 09:04:11 +08:00
|
|
|
cxxFile << "namespace " << nameSpace << std::endl;
|
|
|
|
cxxFile << "{" << std::endl;
|
|
|
|
// 3. 写入类构造函数实现
|
|
|
|
cxxFile << className << "::" << className << "()" << std::endl;
|
|
|
|
cxxFile << "{" << std::endl;
|
|
|
|
for (const auto &interface : interfaceData) {
|
|
|
|
cxxFile << "\t" << "MAP_DATA_FUNC(" << interface.interfaceName << ");" << std::endl;
|
|
|
|
}
|
|
|
|
cxxFile << "}" << std::endl;
|
|
|
|
// 4. 写入类析构函数实现
|
|
|
|
cxxFile << className << "::~" << className << "()" << std::endl;
|
|
|
|
cxxFile << "{" << std::endl;
|
|
|
|
cxxFile << "}" << std::endl;
|
|
|
|
// 5. 写入类初始化函数实现
|
|
|
|
cxxFile << "void " << className
|
|
|
|
<< "::Initialize(XNFrameworkPtr framework, uint32_t modelId,uint32_t DDS_type)"
|
|
|
|
<< std::endl;
|
|
|
|
cxxFile << "{" << std::endl;
|
|
|
|
cxxFile << "\t" << "auto ddsManager = framework->GetDDSManager();" << std::endl;
|
|
|
|
cxxFile << "\t" << "if (!ddsManager) {" << std::endl;
|
|
|
|
cxxFile << "\t\t" << "LOG_ERROR(\"DDSManager is nullptr\");" << std::endl;
|
|
|
|
cxxFile << "\t\t" << "return;" << std::endl;
|
|
|
|
cxxFile << "\t" << "}" << std::endl;
|
|
|
|
cxxFile << "\t" << "if (DDS_type == 0) {" << std::endl; // 读取与发送都进行
|
|
|
|
cxxFile << "\t\t" << "dataWriter = ddsManager->RegisterPublisher<" << topicType
|
|
|
|
<< "PubSubType>(\"" << topicType << "\", modelId);" << std::endl;
|
|
|
|
cxxFile << "\t\t" << "ddsManager->RegisterSubscriber<" << topicType << "PubSubType>(\""
|
|
|
|
<< topicType << "\", modelId, std::bind(&" << className
|
|
|
|
<< "::inputDataListener, this, std::placeholders::_1));" << std::endl;
|
|
|
|
cxxFile << "\t" << "}" << std::endl;
|
|
|
|
cxxFile << "\t" << "else if (DDS_type == 1) {" << std::endl; // 只读取
|
|
|
|
cxxFile << "\t\t" << "ddsManager->RegisterSubscriber<" << topicType << "PubSubType>(\""
|
|
|
|
<< topicType << "\", modelId, std::bind(&" << className
|
|
|
|
<< "::inputDataListener, this, std::placeholders::_1));" << std::endl;
|
|
|
|
cxxFile << "\t" << "}" << std::endl;
|
|
|
|
cxxFile << "\t" << "else if (DDS_type == 2) {" << std::endl; // 只发送
|
|
|
|
cxxFile << "\t\t" << "dataWriter = ddsManager->RegisterPublisher<" << topicType
|
|
|
|
<< "PubSubType>(\"" << topicType << "\", modelId);" << std::endl;
|
|
|
|
cxxFile << "\t" << "}" << std::endl;
|
|
|
|
cxxFile << "}" << std::endl;
|
|
|
|
// 6. 写入清空数据函数实现
|
|
|
|
cxxFile << "void " << className << "::clearOutData()" << std::endl;
|
|
|
|
cxxFile << "{" << std::endl;
|
|
|
|
cxxFile << "\t" << "this->out_data = " << topicType << "();" << std::endl;
|
|
|
|
cxxFile << "}" << std::endl;
|
|
|
|
// 7. 写入发送数据函数实现
|
|
|
|
cxxFile << "void " << className << "::sendOutData()" << std::endl;
|
|
|
|
cxxFile << "{" << std::endl;
|
|
|
|
cxxFile << "\t" << "if (dataWriter) {" << std::endl;
|
|
|
|
cxxFile << "\t\t" << "dataWriter->write(&this->out_data);" << std::endl;
|
|
|
|
cxxFile << "\t" << "}" << std::endl;
|
|
|
|
cxxFile << "}" << std::endl;
|
|
|
|
// 8. 写入输入数据监听函数实现
|
|
|
|
cxxFile << "void " << className << "::inputDataListener(const " << topicType << " &input)"
|
|
|
|
<< std::endl;
|
|
|
|
cxxFile << "{" << std::endl;
|
|
|
|
cxxFile << "\t" << "this->data = input;" << std::endl;
|
|
|
|
cxxFile << "}" << std::endl;
|
|
|
|
// 9. 写入命名空间实现结束
|
|
|
|
cxxFile << "}" << std::endl;
|
|
|
|
cxxFile.close();
|
|
|
|
return true;
|
|
|
|
}
|