/** * @file PluginGenerator.cpp * @brief 简化的插件生成器实现 */ #include "PluginGenerator.h" std::string GetXNCorePath() { const char *xnCorePath = std::getenv("XNCore"); if (xnCorePath != nullptr) { return std::string(xnCorePath); } return ""; } PluginGenerator::PluginGenerator() { } PluginGenerator::~PluginGenerator() { } bool PluginGenerator::loadPluginFromDatabase(const int confID) { std::string xncorePath = GetXNCorePath(); if (xncorePath.empty()) { m_lastError = "无法获取XNCore环境变量的值!"; return false; } std::string dbPath = xncorePath + "/database/XNSim.db"; if (!std::filesystem::exists(dbPath)) { m_lastError = "数据库文件不存在!"; return false; } sqlite3 *db = nullptr; int rc = sqlite3_open(dbPath.c_str(), &db); if (rc != SQLITE_OK) { m_lastError = "无法打开数据库: " + std::string(sqlite3_errmsg(db)); sqlite3_close(db); return false; } // 准备SQL语句查询Configuration表 const char *sql = "SELECT ConfName FROM Configuration WHERE ConfID = ?"; sqlite3_stmt *stmt = nullptr; rc = sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr); if (rc != SQLITE_OK) { m_lastError = "SQL准备失败: " + std::string(sqlite3_errmsg(db)); sqlite3_close(db); return false; } // 绑定参数 sqlite3_bind_int(stmt, 1, confID); // 执行查询 if (sqlite3_step(stmt) == SQLITE_ROW) { const char *text = reinterpret_cast(sqlite3_column_text(stmt, 0)); m_pluginInfo.pluginName = text ? text : ""; m_pluginInfo.interfaceHeaderPath = "../IDL/" + m_pluginInfo.pluginName + "_Interface.h"; m_pluginInfo.outputDirectory = xncorePath + "/Configuration/" + m_pluginInfo.pluginName + "/PluginCode"; } else { m_lastError = "未找到ConfID为 " + std::to_string(confID) + " 的配置"; sqlite3_finalize(stmt); sqlite3_close(db); return false; } // 清理资源 sqlite3_finalize(stmt); // 查询DataInterface_{ConfID}表获取接口信息 std::string dataInterfaceTableName = "DataInterface_" + std::to_string(confID); std::string dataInterfaceSql = "SELECT DISTINCT ModelStructName, SystemName, PlaneName, ATAName FROM " + dataInterfaceTableName; sqlite3_stmt *dataInterfaceStmt = nullptr; rc = sqlite3_prepare_v2(db, dataInterfaceSql.c_str(), -1, &dataInterfaceStmt, nullptr); if (rc != SQLITE_OK) { m_lastError = "DataInterface表SQL准备失败: " + std::string(sqlite3_errmsg(db)); sqlite3_close(db); return false; } // 执行查询并收集接口信息 while (sqlite3_step(dataInterfaceStmt) == SQLITE_ROW) { InterfaceInfo interface; interface.interfaceName = reinterpret_cast(sqlite3_column_text(dataInterfaceStmt, 0)); std::string systemName = reinterpret_cast(sqlite3_column_text(dataInterfaceStmt, 1)); std::string planeName = reinterpret_cast(sqlite3_column_text(dataInterfaceStmt, 2)); std::string ataName = reinterpret_cast(sqlite3_column_text(dataInterfaceStmt, 3)); interface.templateType = systemName + "::" + planeName + "::" + ataName + "::" + interface.interfaceName + "_Interface"; // 使用ModelStructName去重 bool isDuplicate = false; for (const auto &existingInterface : m_pluginInfo.interfaces) { if (existingInterface.interfaceName == interface.interfaceName) { isDuplicate = true; break; } } if (!isDuplicate) { m_pluginInfo.interfaces.push_back(interface); } } // 清理DataInterface查询资源 sqlite3_finalize(dataInterfaceStmt); sqlite3_close(db); return true; } bool PluginGenerator::generatePluginCpp() { std::string content = generatePluginCppContent(); std::string filePath = m_pluginInfo.outputDirectory + "/" + m_pluginInfo.pluginName + "_plugin.cpp"; return writeFile(filePath, content); } bool PluginGenerator::generateCMakeLists() { std::string content = generateCMakeListsContent(); std::string filePath = m_pluginInfo.outputDirectory + "/CMakeLists.txt"; return writeFile(filePath, content); } bool PluginGenerator::compilePlugin() { std::string buildDir = m_pluginInfo.outputDirectory + "/build"; // 如果build目录已存在则删除 if (std::filesystem::exists(buildDir)) { try { std::filesystem::remove_all(buildDir); } catch (const std::exception &e) { m_lastError = "Failed to remove existing build directory: " + std::string(e.what()); return false; } } // 创建build目录 if (!createDirectory(buildDir)) { m_lastError = "Failed to create build directory: " + buildDir; return false; } // 构建命令 std::string cmakeCmd = "cd " + buildDir + " && cmake .."; std::string makeCmd = "cd " + buildDir + " && make"; std::string installCmd = "cd " + buildDir + " && make install"; // 执行cmake int cmakeResult = system(cmakeCmd.c_str()); if (cmakeResult != 0) { m_lastError = "CMake failed with exit code: " + std::to_string(cmakeResult); return false; } // 执行make int makeResult = system(makeCmd.c_str()); if (makeResult != 0) { m_lastError = "Make failed with exit code: " + std::to_string(makeResult); return false; } // 执行make install int installResult = system(installCmd.c_str()); if (installResult != 0) { m_lastError = "Make install failed with exit code: " + std::to_string(installResult); return false; } return true; } std::string PluginGenerator::getLastError() const { return m_lastError; } std::string PluginGenerator::generatePluginCppContent() { std::stringstream ss; // 生成头文件包含 ss << "#include \n"; ss << "#include \n"; ss << "// " << m_pluginInfo.pluginName << "接口头文件 - 只在插件中包含\n"; ss << "#include \"" << m_pluginInfo.interfaceHeaderPath << "\"\n\n"; // 生成插件信息 ss << "// 插件信息\n"; ss << "static PluginInfo plugin_info = {\"" << m_pluginInfo.pluginName << "\", \"" << "" << "\", DATAMONITOR_PLUGIN_INTERFACE_VERSION};\n\n"; // 生成支持的接口列表 ss << "// 支持的接口列表\n"; ss << "static const char *supported_interfaces[] = {\n"; for (size_t i = 0; i < m_pluginInfo.interfaces.size(); ++i) { ss << " \"" << m_pluginInfo.interfaces[i].interfaceName << "\""; if (i < m_pluginInfo.interfaces.size() - 1) { ss << ","; } ss << "\n"; } ss << "};\n\n"; ss << "static const int interface_count = sizeof(supported_interfaces) / " "sizeof(supported_interfaces[0]);\n\n"; // 生成导出的插件函数 ss << "// 导出的插件函数\n"; ss << "extern \"C\"\n"; ss << "{\n\n"; // get_plugin_info函数 ss << " PluginInfo *get_plugin_info()\n"; ss << " {\n"; ss << " return &plugin_info;\n"; ss << " }\n\n"; // create_monitor函数 ss << " DataMonitorBasePtr create_monitor(const char *interfaceName)\n"; ss << " {\n"; ss << " std::string name(interfaceName);\n\n"; for (size_t i = 0; i < m_pluginInfo.interfaces.size(); ++i) { const auto &interface = m_pluginInfo.interfaces[i]; ss << " if (name == \"" << interface.interfaceName << "\") {\n"; ss << " return std::make_shared>();\n"; ss << " }"; if (i < m_pluginInfo.interfaces.size() - 1) { ss << " else"; } ss << "\n"; } ss << " return nullptr;\n"; ss << " }\n\n"; // destroy_monitor函数 ss << " void destroy_monitor(const char *interfaceName)\n"; ss << " {\n"; ss << " // 智能指针会自动管理内存,这里可以添加额外的清理逻辑\n"; ss << " }\n\n"; // get_supported_interfaces函数 ss << " const char **get_supported_interfaces(int *count)\n"; ss << " {\n"; ss << " if (count) {\n"; ss << " *count = interface_count;\n"; ss << " }\n"; ss << " return const_cast(supported_interfaces);\n"; ss << " }\n\n"; // free_string_array函数 ss << " void free_string_array(const char **array)\n"; ss << " {\n"; ss << " // 这里不需要释放,因为使用的是静态数组\n"; ss << " }\n"; ss << "}\n"; return ss.str(); } std::string PluginGenerator::generateCMakeListsContent() { std::stringstream ss; std::string projectName = m_pluginInfo.pluginName + "_Monitor"; ss << "# CMakeLists.txt for " << projectName << " plugin\n"; ss << "cmake_minimum_required(VERSION 3.10)\n\n"; ss << "# 设置项目名称\n"; ss << "project(" << projectName << "_plugin)\n\n"; ss << "# 设置C++标准\n"; ss << "set(CMAKE_CXX_STANDARD 17)\n"; ss << "set(CMAKE_CXX_STANDARD_REQUIRED ON)\n\n"; ss << "# 查找必要的包\n"; ss << "find_package(PkgConfig REQUIRED)\n"; ss << "find_package(FastDDS REQUIRED)\n"; ss << "if(DEFINED ENV{XNCore})\n"; ss << " set(XNCore_PATH $ENV{XNCore})\n"; ss << "else()\n"; ss << " message(FATAL_ERROR \"Environment variable XNCore is not set.\")\n"; ss << "endif()\n"; ss << "include_directories(${XNCore_PATH}/include)\n"; ss << "# 创建插件库\n"; ss << "add_library(" << projectName << " SHARED\n"; ss << " " << m_pluginInfo.pluginName << "_plugin.cpp\n"; ss << ")\n\n"; ss << "# 链接库\n"; ss << "target_link_libraries(" << projectName << "\n"; ss << " fastcdr\n"; ss << " fastdds\n"; ss << " OpenSSL::SSL\n"; ss << " OpenSSL::Crypto\n"; ss << " ${XNCore_PATH}/lib/lib" << m_pluginInfo.pluginName << "_Interface.so\n"; ss << " ${XNCore_PATH}/lib/libXNMonitorServer.so\n"; ss << ")\n\n"; ss << "target_compile_definitions(" << projectName << " PRIVATE " << projectName << "_LIBRARY)\n"; ss << "if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)\n"; ss << " set(CMAKE_INSTALL_PREFIX \"${XNCore_PATH}/Configuration/" << m_pluginInfo.pluginName << "/Plugins\" CACHE PATH \"Install path prefix\" " "FORCE)\n"; ss << "endif()\n"; ss << "include(GNUInstallDirs)\n"; ss << "install(TARGETS " << projectName << "\n"; ss << " BUNDLE DESTINATION .\n"; ss << " LIBRARY DESTINATION .\n"; ss << " RUNTIME DESTINATION .\n"; ss << ")\n"; return ss.str(); } bool PluginGenerator::writeFile(const std::string &filePath, const std::string &content) { try { // 确保目录存在 std::filesystem::path path(filePath); if (path.has_parent_path()) { createDirectory(path.parent_path().string()); } std::ofstream file(filePath); if (!file.is_open()) { m_lastError = "无法创建文件: " + filePath; return false; } file << content; file.close(); return true; } catch (const std::exception &e) { m_lastError = "写入文件错误: " + std::string(e.what()); return false; } } bool PluginGenerator::createDirectory(const std::string &dirPath) { try { if (!std::filesystem::exists(dirPath)) { return std::filesystem::create_directories(dirPath); } return true; } catch (const std::exception &e) { m_lastError = "创建目录错误: " + std::string(e.what()); return false; } } const GenPluginInfo &PluginGenerator::getPluginInfo() const { return m_pluginInfo; }