#include "ToolDepository.h" // QT运行库相关的文件夹和dll名称(用于识别tools的时候进行排除,仅用于Qt6) #define QT_PLATFORMS "platforms" #define QT6_DEBUG_DLL1 "Qt6Cored.dll" #define QT6_DEBUG_DLL2 "Qt6Guid.dll" #define QT6_DEBUG_DLL3 "Qt6Widgetsd.dll" #define QT6_RELEASE_DLL1 "Qt6Core.dll" #define QT6_RELEASE_DLL2 "Qt6Gui.dll" #define QT6_RELEASE_DLL3 "Qt6Widgets.dll" // 内置的工具的默认分类名称(包括Port工具、注释工具、Goto工具等) #define BUILDIN_CATEGORY_NAME ("内置工具") // 工具仓库实例 ToolDepository toolDepository; ToolDepository::ToolDepository() { } ToolDepository::~ToolDepository() { } //////////////////////////////////////////////////////////// // 加载文件中保存的工具信息 bool ToolDepository::LoadTools() { // m_TotalTools.clear(); // 确保只加载一次 if (m_TotalTools.size() > 0) { return true; } // 从文件中加载工具信息 this->LoadFromFile(DEFAULT_TOOL_PATH); // 2021-3-29增加,直接在内部生成port工具,不从外部加载了 this->createPortTool(); // 2022-3-15,增加内部生成的Comment工具 this->createCommentTool(); // 2022-3-25,内部生成Goto工具 this->createGotoTool(); // 2022-4-18 生成内置的并行计算工具 this->createParallelTool(); // 2022-8-22 生成内置的ForLoop工具 this->createForLoopTool(); // 2022-9-2 生成内置的Wait工具 this->createWaitTool(); return true; } //////////////////////////////////////////////////////////// // 从文件中加载工具信息 bool ToolDepository::LoadFromFile(const QString& strPath) { QDir dir(strPath); if (!dir.exists() || strPath.indexOf("platforms") > 1) return false; // 取所有的文件和文件名,但是去掉.和..的文件夹 dir.setFilter(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot); // 文件夹优先 dir.setSorting(QDir::DirsFirst); QFileInfoList list = dir.entryInfoList(); int i = 0; while(i < list.size()) { QFileInfo fileInfo = list.at(i); bool bisDir = fileInfo.isDir(); if (bisDir) { LoadFromFile(fileInfo.filePath()); } else { QString strFileName = fileInfo.fileName(); // 加载所有的dll工具 if (strFileName.endsWith(TOOL_EXT) // 跳过Qt6相关运行Dll //&& strFileName.compare(QT6_DEBUG_DLL1) != 0 //&& strFileName.compare(QT6_DEBUG_DLL2) != 0 //&& strFileName.compare(QT6_DEBUG_DLL3) != 0 //&& strFileName.compare(QT6_RELEASE_DLL1) != 0 //&& strFileName.compare(QT6_RELEASE_DLL2) != 0 //&& strFileName.compare(QT6_RELEASE_DLL3) != 0 ) { QString strDllFullPath = fileInfo.absoluteFilePath(); // 取出新的dll工具信息,加入到集合中 if (!ParseToolsFromDll(strDllFullPath, strFileName)) { // Report Error // 2021-8-5,居然发现了一个隐藏多年的bug,此处会导致代码死循环 i++; continue; } } } i++; }; return true; } ///////////////////////////////////////////////////////////// // 从dll中提取工具信息 bool ToolDepository::ParseToolsFromDll(const QString& strDllPath, const QString& strDllName) { // 加载Dll // 2021-01-17,设计思路调整,此处工具仓库加载完工具信息后,直接释放掉,后面用到的时候再加载,优化资源占用 QLibrary dllTool(strDllPath); if (!dllTool.load()) { vWarning() << "[Error] ToolDepository::ParseToolsFromDll - load [" << strDllName << "] failed, Reason:" << dllTool.errorString(); return false; } // 调用NewToolPtr接口 typedef DllTool* (*GETTOOL)(); GETTOOL GetTool = (GETTOOL)dllTool.resolve(FUNCTION_GETTOOL); if (GetTool == nullptr) { qDebug() << "[Error] ToolDepository::ParseToolsFromDll - [" << strDllName << "] GetTool failed, Reason:" << dllTool.errorString(); return false; } // 获取指针 DllTool* pDllPtr = GetTool(); if (pDllPtr == nullptr) { qDebug() << "[Error] ToolDepository::ParseToolsFromDll - [" << strDllName << "] GetTool failed, Reason:" << dllTool.errorString(); return false; } // 初始化工具信息 // 2021-8-2 改成了将dll中的参数值传递进exe中,否则event带不进来 pDllPtr->InitTool(); // 获取工具描述 const DLL_TOOL_DESC& toolDescriotion = pDllPtr->Description(); STATIC_TOOL newStaticTool; newStaticTool.Type = toolDescriotion.Type; newStaticTool.strName = toolDescriotion.strName; newStaticTool.strAliasName = toolDescriotion.strAliasName; newStaticTool.strCategory = toolDescriotion.strCategory; newStaticTool.strVersion = toolDescriotion.strVersion; newStaticTool.strDllPath = strDllPath; newStaticTool.strInfo = toolDescriotion.strInfo; // 对于某些未设置别名的工具,就将工具名称设置为别名 if (newStaticTool.strAliasName.isEmpty()) { newStaticTool.strAliasName = newStaticTool.strName; } // 获取工具接口信息 for (int i = 0; i < pDllPtr->GetInterfaceSize(); i++) { const DLL_INF& dllinf = pDllPtr->Interface(i); STATIC_INTERFACE newStaticInf; newStaticInf.strName = dllinf.strName; newStaticInf.Direction = dllinf.Direction; newStaticInf.Discard = dllinf.Discard; newStaticInf.Type = dllinf.Type; // 2021-8-2 ,将value改成了从dll中全部复制,否则dll中的event带不进来 //newStaticInf.value = dllinf.value; //newStaticInf.value.Ptr = nullptr; // 2022-9-19,如果是Event类型的接口,此处要把Dll中的Event拷贝进来 // MEMO:值在这里拷贝没有意义,因为执行到这里的时候,Tool那边是采用空值初始化的,这里的Value值都是空的 // 这里无需复制,在PouScene中添加完工具执行 pNewTool->pDllPtr->InitTool() 的时候才是带值初始化 // 而且原则上exe中是不保存dll中的值的,所以需要用到dll中值的时候应该直接过去取,而不是拷贝到exe中 // 所以Event的值是在Task绑定event句柄的时候,直接从dll中取值了,而不是从这里拷贝过来 //if (newStaticInf.Type == INF_TYPE::INF_TYPE_EVENT) //{ // newStaticInf.value.Ptr = dllinf.value.Ptr; //} // newStaticInf.eventTrigger = dllinf.eventTrigger; newStaticInf.value.passMode = dllinf.value.passMode; newStaticInf.value.type = dllinf.value.type; newStaticInf.nIndex = i; newStaticInf.bEnable = dllinf.bEnable; newStaticTool.staticInterfaces.push_back(newStaticInf); } //newTool.hIcon = (HICON)::LoadImage(hDllTool, MAKEINTRESOURCE(IDR_MAINFRAME), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE); //g_imagelist->Add(newTool.hIcon); // 调用ReleaseToolPtr接口 typedef void (*RELEASETOOL)(); RELEASETOOL ReleaseTool = (RELEASETOOL)dllTool.resolve(FUNCTION_RELEASETOOL); if (ReleaseTool == nullptr) { // CUtility::CriticalMessageBox(_T("获取ReleaseToolPtr 失败!\n\n%s"), strDllPath.GetString()); qDebug() << "[Error] ToolDepository::ParseToolsFromDll - [" << strDllName << "] ReleaseTool failed, Reason:" << dllTool.errorString(); return false; } // 2021-3-29 增加,只加入标准类型工具 if (newStaticTool.isStandardTool()) { // 添加到工具集中 AddToCategory(newStaticTool, toolDescriotion.strCategory); m_toolDllPaths.insert(newStaticTool.strName, newStaticTool.strDllPath); qDebug() << "ToolDepository::ParseToolsFromDll - Add [" << strDllName << "] to toolbox."; } else { qDebug() << "ToolDepository::ParseToolsFromDll - Ignore [" << strDllName << "], Reason: is not standard tool."; } // 释放工具内存 ReleaseTool(); // dllTool.unload(); return true; } ///////////////////////////////////////////////////////////// // 将工具信息添加到Category中 bool ToolDepository::AddToCategory(const STATIC_TOOL& newTool, const QString& strCategoryName) { // 找到对应的Category,添加 for (int i = 0; i < m_TotalTools.size(); i++) { TOOL_CATEGORY& cate = m_TotalTools[i]; if (cate.strName.compare(strCategoryName) == 0) { cate.staticTools.push_back(newTool); return true; } } // 如果没找到,则建一个新的工具集 TOOL_CATEGORY cate; cate.strName = strCategoryName; cate.staticTools.push_back(newTool); m_TotalTools.push_back(cate); return true; } /// /// 2021-3-29增加,直接在内部生成port工具,不从外部加载了 /// void ToolDepository::createPortTool() { // Output m_toolPortOutput.Type = TOOL_TYPE::TOOL_TYPE_PORT_OUTPUT; m_toolPortOutput.strName = ("OutputPort");; m_toolPortOutput.strAliasName = m_toolPortOutput.strName; m_toolPortOutput.strVersion = ("2.0"); m_toolPortOutput.strDllPath = (""); m_toolPortOutput.strInfo = ("Output port tool."); STATIC_INTERFACE newStaticInf; newStaticInf.strName = (""); newStaticInf.Direction = INF_DIRECTION::INF_DIR_OUT; newStaticInf.Type = INF_TYPE::INF_TYPE_UNKNOWN; newStaticInf.value.passMode = VALUE_PASS_MODE::PASS_BY_UNKNOWN; newStaticInf.value.type = VALUE_TYPE::Type_Unknown; newStaticInf.value.Ptr = nullptr; newStaticInf.nIndex = 0; newStaticInf.bEnable = true; m_toolPortOutput.staticInterfaces.push_back(newStaticInf); AddToCategory(m_toolPortOutput, BUILDIN_CATEGORY_NAME); // Input m_toolPortInput.Type = TOOL_TYPE::TOOL_TYPE_PORT_INPUT; m_toolPortInput.strName = ("InputPort");; m_toolPortInput.strAliasName = m_toolPortInput.strName; m_toolPortInput.strVersion = ("2.0"); m_toolPortInput.strDllPath = (""); m_toolPortInput.strInfo = ("Input port tool."); newStaticInf.strName = (""); newStaticInf.Direction = INF_DIRECTION::INF_DIR_IN; newStaticInf.Type = INF_TYPE::INF_TYPE_UNKNOWN; newStaticInf.value.passMode = VALUE_PASS_MODE::PASS_BY_UNKNOWN; newStaticInf.value.type = VALUE_TYPE::Type_Unknown; newStaticInf.value.Ptr = nullptr; newStaticInf.nIndex = 0; newStaticInf.bEnable = true; m_toolPortInput.staticInterfaces.push_back(newStaticInf); AddToCategory(m_toolPortInput, BUILDIN_CATEGORY_NAME); } /// /// 2022-3-13 内置注释工具 /// void ToolDepository::createCommentTool() { m_toolComment.Type = TOOL_TYPE::TOOL_TYPE_COMMENT; m_toolComment.strName = ("Comment");; m_toolComment.strAliasName = m_toolComment.strName; m_toolComment.strVersion = ("1.0"); m_toolComment.strDllPath = (""); m_toolComment.strInfo = ("DoubleClick to edit content."); AddToCategory(m_toolComment, BUILDIN_CATEGORY_NAME); } /// /// 2022-3-22 生成内置的Goto工具 /// void ToolDepository::createGotoTool() { m_toolGoto.Type = TOOL_TYPE::TOOL_TYPE_GOTO; m_toolGoto.strName = ("Goto");; m_toolGoto.strAliasName = m_toolGoto.strName; m_toolGoto.strVersion = ("1.0"); m_toolGoto.strDllPath = (""); m_toolGoto.strInfo = (""); // 输入接口固定为bool STATIC_INTERFACE newStaticInf; newStaticInf.strName = ("bool"); // 虽然设置了,但是不显示输入接口名称 newStaticInf.Direction = INF_DIRECTION::INF_DIR_IN; newStaticInf.Type = INF_TYPE::INF_TYPE_STANDARD; newStaticInf.value.passMode = VALUE_PASS_MODE::PASS_BY_VALUE; newStaticInf.value.type = VALUE_TYPE::Type_Bool; // 输入接口默认值为false // m_bDefaultGotoInput = false; // newStaticInf.value.Ptr = (void**)&m_bDefaultGotoInput; newStaticInf.value.setValue(false); newStaticInf.nIndex = 0; newStaticInf.bEnable = true; newStaticInf.bShowName = false; // Goto的输入接口不显示名字 m_toolGoto.staticInterfaces.push_back(newStaticInf); // 输出接口为空,等待绑定 newStaticInf.reset(); newStaticInf.strName = ("Output"); newStaticInf.Direction = INF_DIRECTION::INF_DIR_OUT; newStaticInf.Type = INF_TYPE::INF_TYPE_TOOL; // 设置为Tool的输出接口,用于链接Tool newStaticInf.value.passMode = VALUE_PASS_MODE::PASS_BY_VALUE; newStaticInf.value.type = VALUE_TYPE::Type_Tool; // 设置为Tool类型,表示连接到Tool类型的接口 newStaticInf.value.Ptr = nullptr; newStaticInf.nIndex = 0; newStaticInf.bEnable = true; newStaticInf.bShowName = false; // Goto的输出接口默认不显示名字,绑定后才显示 m_toolGoto.staticInterfaces.push_back(newStaticInf); AddToCategory(m_toolGoto, BUILDIN_CATEGORY_NAME); } /// /// 2022-4-18 生成内置的并行计算工具 /// void ToolDepository::createParallelTool() { // 工具信息 m_toolParallel.Type = TOOL_TYPE::TOOL_TYPE_PARALLEL; m_toolParallel.strName = ("Parallel");; m_toolParallel.strAliasName = m_toolParallel.strName; m_toolParallel.strVersion = ("1.0"); m_toolParallel.strDllPath = (""); m_toolParallel.strInfo = (""); // 接口信息 STATIC_INTERFACE newStaticInf; // 2022-4-28 屏蔽,为了和标准工具统一,输入接口移至到运行时动态增加 // 输入接口(用于绑定Goto,Top类型) //newStaticInf.strName = ("Top.In"); // 虽然设置了,但是不显示输入接口名称 //newStaticInf.Direction = INF_DIRECTION::INF_DIR_IN; //newStaticInf.Type = INF_TYPE::INF_TYPE_TOP; //newStaticInf.value.passMode = VALUE_PASS_MODE::PASS_BY_VALUE; //newStaticInf.value.type = VALUE_TYPE::Type_Tool; // 设置为Tool类型,表示只能接收Goto连接 //newStaticInf.value.Ptr = nullptr; //newStaticInf.nIndex = 0; //newStaticInf.bEnable = true; //newStaticInf.bShowName = false; // 并行工具的输入接口不显示名字 //m_toolParallel.staticInterfaces.push_back(newStaticInf); //newStaticInf.reset(); //newStaticInf.strName = ("Tool.End"); //newStaticInf.Direction = INF_DIRECTION::INF_DIR_OUT; //newStaticInf.Type = INF_TYPE::INF_TYPE_TOOL; // 设置为Tool的输出接口,用于链接Tool //newStaticInf.value.passMode = VALUE_PASS_MODE::PASS_BY_VALUE; //newStaticInf.value.type = VALUE_TYPE::Type_Tool; // 设置为Tool类型,表示连接到Tool类型的接口 //newStaticInf.value.Ptr = nullptr; //newStaticInf.nIndex = 0; //newStaticInf.bEnable = true; //newStaticInf.bShowName = false; // 输出接口默认不显示名字 //m_toolParallel.staticInterfaces.push_back(newStaticInf); AddToCategory(m_toolParallel, BUILDIN_CATEGORY_NAME); } /// /// 2022-8-22 生成内置的For循环工具 /// void ToolDepository::createForLoopTool() { // 工具信息 m_toolForLoop.Type = TOOL_TYPE::TOOL_TYPE_FORLOOP; m_toolForLoop.strName = ("ForLoop");; m_toolForLoop.strAliasName = m_toolForLoop.strName; m_toolForLoop.strVersion = ("1.0"); m_toolForLoop.strDllPath = (""); m_toolForLoop.strInfo = (""); // 接口信息 STATIC_INTERFACE newStaticInf; //// 默认ToolEnd接口,用于链接循环工具 //newStaticInf.strName = ("Tool.End"); //newStaticInf.Direction = INF_DIRECTION::INF_DIR_OUT; //newStaticInf.Type = INF_TYPE::INF_TYPE_TOOL; // 设置为Tool的输出接口,用于链接Tool //newStaticInf.value.passMode = VALUE_PASS_MODE::PASS_BY_VALUE; //newStaticInf.value.type = VALUE_TYPE::Type_Tool; // 设置为Tool类型,表示连接到Tool类型的接口 //newStaticInf.value.Ptr = nullptr; //newStaticInf.nIndex = 1; //newStaticInf.bEnable = true; //newStaticInf.bShowName = false; // 输出接口默认不显示名字 //m_toolForLoop.staticInterfaces.push_back(newStaticInf); // 默认size输入接口,用于确定循环体的执行次数 newStaticInf.strName = ("size"); // size接口名称 newStaticInf.Direction = INF_DIRECTION::INF_DIR_IN; newStaticInf.Type = INF_TYPE::INF_TYPE_STANDARD; newStaticInf.value.passMode = VALUE_PASS_MODE::PASS_BY_VALUE; newStaticInf.value.type = VALUE_TYPE::Type_Int; // 输入接口不需要默认值,全靠上级接口Link进来 // newStaticInf.value.setValue(0); newStaticInf.nIndex = 0; newStaticInf.bEnable = true; newStaticInf.bShowName = true; // 显示接口名称 m_toolForLoop.staticInterfaces.push_back(newStaticInf); // 默认index输出接口,用于输出当前For循环的index newStaticInf.strName = ("index"); // Index接口名称 newStaticInf.Direction = INF_DIRECTION::INF_DIR_OUT; newStaticInf.Type = INF_TYPE::INF_TYPE_STANDARD; newStaticInf.value.passMode = VALUE_PASS_MODE::PASS_BY_VALUE; newStaticInf.value.type = VALUE_TYPE::Type_Int; //// 输出接口默认值为0(不需要默认值,运行时再设置) //newStaticInf.value.setValue(0); newStaticInf.nIndex = 1; newStaticInf.bEnable = true; newStaticInf.bShowName = true; // 显示接口名称 m_toolForLoop.staticInterfaces.push_back(newStaticInf); AddToCategory(m_toolForLoop, BUILDIN_CATEGORY_NAME); } /// /// 2022-9-2 生成内置的等待Event工具 /// void ToolDepository::createWaitTool() { // 工具信息 m_toolWait.Type = TOOL_TYPE::TOOL_TYPE_WAIT; m_toolWait.strName = ("Wait");; m_toolWait.strAliasName = m_toolForLoop.strName; m_toolWait.strVersion = ("1.0"); m_toolWait.strDllPath = (""); m_toolWait.strInfo = (""); // 接口信息 STATIC_INTERFACE newStaticInf; // 默认waitValue输出接口,用于输出工具当前等待的值 newStaticInf.strName = ("waitValue"); // 接口名称 newStaticInf.Direction = INF_DIRECTION::INF_DIR_OUT; newStaticInf.Type = INF_TYPE::INF_TYPE_STANDARD; newStaticInf.value.passMode = VALUE_PASS_MODE::PASS_BY_VALUE; newStaticInf.value.type = VALUE_TYPE::Type_Int; // 接口默认值 // newStaticInf.value.setValue(0); newStaticInf.nIndex = 0; newStaticInf.bEnable = true; newStaticInf.bShowName = true; // 显示接口名称 m_toolWait.staticInterfaces.push_back(newStaticInf); // 默认waitTime输出接口,用于输出当前启动后等待的总时长 newStaticInf.strName = ("waitTime"); // 接口名称 newStaticInf.Direction = INF_DIRECTION::INF_DIR_OUT; newStaticInf.Type = INF_TYPE::INF_TYPE_STANDARD; newStaticInf.value.passMode = VALUE_PASS_MODE::PASS_BY_VALUE; newStaticInf.value.type = VALUE_TYPE::Type_Int; //// 输出接口默认值为0(不需要默认值,运行时再设置) //newStaticInf.value.setValue(0); newStaticInf.nIndex = 1; newStaticInf.bEnable = true; newStaticInf.bShowName = true; // 显示接口名称 m_toolWait.staticInterfaces.push_back(newStaticInf); AddToCategory(m_toolWait, BUILDIN_CATEGORY_NAME); } /// /// 根据名称,获取工具 (根据名字或者曾用名) /// /// /// TOOL* ToolDepository::getToolByName(QString strName) { TOOL* pTool = nullptr; for (int i = 0; i < toolDepository.m_TotalTools.size(); i++) { const TOOL_CATEGORY& cate = toolDepository.m_TotalTools[i]; for (int j = 0; j < cate.staticTools.size(); j++) { const STATIC_TOOL& tool = cate.staticTools[j]; if (tool.strName == strName || tool.strAliasName == strName) { pTool = new TOOL(&tool); } } } return pTool; } /// /// 获取指定DLL的指针 /// /// /// DllTool* ToolDepository::GetToolPtr(const QString& strToolName) { const QString& strDllPath = GetDllPathByName(strToolName); if (strDllPath.isEmpty()) { return nullptr; } // 加载指定dll QLibrary dllTool(strDllPath); if (!dllTool.load()) { return nullptr; } // 调用GetToolPtr接口 typedef DllTool* (*GETTOOL)(); GETTOOL GetTool = (GETTOOL)dllTool.resolve(FUNCTION_GETTOOL); if (GetTool == nullptr) { return nullptr; } // 获取指针 DllTool* pDllPtr = GetTool(); if (pDllPtr == nullptr) { return nullptr; } return pDllPtr; } /// /// 获取指定DLL的全路径 /// /// /// QString ToolDepository::GetDllPathByName(const QString& strToolName) { if (m_toolDllPaths.contains(strToolName)) { return m_toolDllPaths.value(strToolName); } else { return ""; } } //////////////////////////////////////////////// //// 释放工具dll //void CToolManager::FreeToolsLibrary() //{ // for (unsigned int i = 0; i < m_TotalTools.size(); i++) // { // TOOL_CATEGORY& cate = m_TotalTools[i]; // // for (unsigned int j = 0; j < cate.Tools.size(); j++) // { // TOOL& mtool = cate.Tools[j]; // mtool.Interfaces.clear(); // // // RELEASE_BUFFER(mtool.pDllPtr); // // //// 加载dll // //if (mtool.hDllTool) // //{ // // // 调用Release接口 // // typedef void(*RELEASE)(); // // RELEASE Release = (RELEASE)GetProcAddress(mtool.hDllTool, FUNCTION_RELEASE); // // if (Release) // // { // // Release(); // // } // // FreeLibrary(mtool.hDllTool); // //} // } // cate.Tools.clear(); // // } // m_TotalTools.clear(); //} // //////////////////////////////////////////////////////// //// 检测Tool的有效性 //bool ToolDepository::ValidateTool(const TOOL& toolInfo) //{ // // 加载Dll // QLibrary dllTool(toolInfo.strDll); // if (!dllTool.load()) // { // // CUtility::CriticalMessageBox(_T("如下工具缺失,加载存档失败!\n\n%s"), toolInfo.strDll); // return false; // } // // // 调用Description接口 // typedef const DLL_TOOL_DESC& (*DESCRIPTION)(); // DESCRIPTION Description = (DESCRIPTION)dllTool.resolve(FUNCTION_DESCRIPTION); // if (Description == nullptr) // { // // 获取版本号失败 // // CUtility::CriticalMessageBox(_T("获取版本号失败!\n\n%s"), toolInfo.strDll); // return false; // } // // // 校验版本号 // const DLL_TOOL_DESC& toolDescriotion = Description(); // if (toolInfo->strVersion.compare(toolDescriotion.strVersion) != 0) // { // //// 版本号不一致 // //CUtility::CriticalMessageBox(_T("版本号不一致!\n\n%s \r\n需要版本号为:%s\r\n本地文件版本号为:%s"), // // toolInfo.strDll, toolInfo.strVersion, toolDescriotion.strVersion); // // return false; // } // // // FreeLibrary(hDllTool); // // return true; //}