/** * @file XNModelManager.cpp * @author jinchao * @brief 模型管理器类源文件 * @version 1.0 * @date 2024-11-06 * * @copyright Copyright (c) 2024 XN * */ #include "XNModelManager.h" #include "XNModelManager_p.h" #include "XNModelObject.h" #include "XNFramework.h" #include "XNThreadManager.h" // 构造函数 XNModelManager::XNModelManager() : XNBaseFrameObject(new XNModelManagerPrivate()) { SetUniqueId(6); SetObjectName("XNModelManager"); T_D(); d->ModelIDAssigned.resize(10000, false); } // 析构函数 XNModelManager::~XNModelManager() { } XNModelManager::XNModelManager(PrivateType *p) : XNBaseFrameObject(p) { T_D(); d->ModelIDAssigned.resize(10000, false); } // 运行前最后准备 bool XNModelManager::PrepareForExecute() { T_D(); for (auto &model : d->ModelMap) { model.second->PrepareForExecute(); } d->_status = XNFrameObjectStatus::Ready; LOG_INFO("XNModelManager is prepared!"); return true; } bool XNModelManager::Initialize() { T_D(); LOG_INFO("XNModelManager Initialize Success!"); d->_status = XNFrameObjectStatus::Initialized; return true; } void XNModelManager::LoadModel(const std::string &modelPath, const std::string &className, const std::string &modelVersion, const std::string &planeName, uint32_t initialType, uint32_t threadID) { T_D(); void *handle = dlopen(modelPath.c_str(), RTLD_LAZY); if (handle) { typedef XNModelObjectPtr (*InitialModelFunc)(); std::string initialModelName = "Initial" + className; InitialModelFunc initialModel = (InitialModelFunc)dlsym(handle, initialModelName.c_str()); if (initialModel) { XNModelObjectPtr model = initialModel(); if (model) { uint32_t modelID = RegisterModel(); if (modelID == 0) { LOG_WARNING("0x2174 Assign Model ID Failed, Model ID is used up!"); dlclose(handle); return; } model->SetUniqueId(modelID); model->SetObjectName(className); model->SetFramework(GetFramework()); model->SetInitializeType(initialType); model->SetThreadID(threadID); std::filesystem::path parentPath = std::filesystem::path(modelPath).parent_path(); model->SetLibPath(parentPath.string()); if (initialType == 0) { // 使用std::filesystem处理路径 std::filesystem::path configPath = parentPath / (className + "_V" + modelVersion + ".mcfg"); model->SetXmlPath(configPath.string()); } else if (initialType == 1) { model->SetXmlPath(planeName + "," + className + "," + modelVersion); } // 注册模型到管理器 d->ModelMap[modelID] = model; // 初始化模型 model->Initialize(); // 注册到线程管理器 if (threadID != 0) { auto framework = GetFramework(); if (framework) { // 注册到线程管理器 (重复注册了,暂删除) // framework->GetThreadManager()->RegisterFunction( // modelID, std::bind(&XNModelObject::StepUpdate, model.get()), threadID, // model->GetRunFreq(), model->GetRunNode(), model->GetRunPriority()); // 设置模型设置频率 double threadFreq = framework->GetThreadManager()->GetThreadFreqByID(threadID); double modelSetFreq = threadFreq / (double)(1 << model->GetRunFreq()); model->SetSetFreq(modelSetFreq); } } } else { LOG_WARNING("0x2173 Model %s Not found in dynamic link library %s!", className.c_str(), modelPath.c_str()); dlclose(handle); return; } } else { LOG_WARNING("0x2177 InitialModel function not found in dynamic link library %s!", modelPath.c_str()); dlclose(handle); return; } } else { LOG_WARNING("0x2172 Model %s Dynamic link library loading failed! Error: %s", className.c_str(), dlerror()); } } // 模型注册 uint32_t XNModelManager::RegisterModel() { T_D(); // 从10000~19999的编号中分配ID for (int i = 0; i < 10000; i++) { if (d->ModelIDAssigned[i]) continue; else { d->ModelIDAssigned[i] = true; return i + 10000; } } return 0; } // 获取模型指针 XNModelObjectPtr XNModelManager::GetModel(uint32_t modelID) { T_D(); if (d->ModelIDAssigned[modelID - 10000]) { auto model = d->ModelMap.find(modelID); if (model != d->ModelMap.end()) { return model->second; } return nullptr; } else return nullptr; } void XNModelManager::RegisterFunction(uint32_t id, XNCallBack fun, uint32_t threadID, uint32_t freqGroup, uint32_t RunPos, uint32_t RunPriorty) { T_D(); if (d->ModelIDAssigned[id - 10000]) { auto framework = GetFramework(); if (framework) { framework->GetThreadManager()->RegisterFunction(id, fun, threadID, freqGroup, RunPos, RunPriorty); } } else { LOG_WARNING( "0x2177 Submission of periodic function was rejected, model ID %1 is not registered!", id); } }