- 添加模块化HTTP服务器架构,支持路由注册和请求处理 - 实现Creo状态检测API,提供连接状态和模型状态实时监控 - 完成STEP格式模型导出功能,支持装配体和零件导出 - 实现装配体层级结构分析,支持无限深度遍历和组件信息提取 - 添加层级组件安全删除功能,使用抑制策略保持装配体完整性 - 集成WebSocket服务器框架,为实时通信和长操作做准备 - 完善JSON处理、日志记录和认证管理基础设施 - 修复OTK API兼容性问题和内存管理优化 - 解决DeleteFeatures崩溃问题,采用SuppressFeatures替代方案 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
627 lines
24 KiB
C++
627 lines
24 KiB
C++
// MFCCreoDll.cpp: 定义 DLL 的初始化例程。
|
||
//
|
||
|
||
#include "pch.h"
|
||
#include "framework.h"
|
||
#include "MFCCreoDll.h"
|
||
#include "HttpServer.h"
|
||
#include "CreoManager.h"
|
||
#include <wfcSession.h>
|
||
#include <wfcGlobal.h>
|
||
#include <string>
|
||
#include <sstream>
|
||
#include <regex>
|
||
#include <mutex>
|
||
#include <atomic>
|
||
#include <memory>
|
||
|
||
#ifdef _DEBUG
|
||
#define new DEBUG_NEW
|
||
#endif
|
||
|
||
// --- 全局变量 ---
|
||
static std::unique_ptr<HttpServer> g_http_server;
|
||
static std::mutex message_mutex;
|
||
static std::string pending_message; // 待处理的消息
|
||
static std::atomic<bool> has_pending_message{false};
|
||
static UINT_PTR timer_id = 0;
|
||
|
||
// --- 辅助函数:将 std::string 转换为 xstring ---
|
||
xstring ConvertStringToXstring(const std::string& str)
|
||
{
|
||
std::wstring wstr(str.begin(), str.end());
|
||
return xstring(wstr.c_str());
|
||
}
|
||
|
||
// 定时器回调函数,在主线程中处理待处理的消息
|
||
VOID CALLBACK TimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
|
||
{
|
||
if (has_pending_message.load()) {
|
||
std::lock_guard<std::mutex> lock(message_mutex);
|
||
if (has_pending_message.load()) {
|
||
has_pending_message = false; // 立即清除标志,避免重复触发
|
||
|
||
try {
|
||
pfcSession_ptr Session = pfcGetCurrentSession();
|
||
if (Session) {
|
||
// 创建字符串序列
|
||
xstringsequence_ptr messages = xstringsequence::create();
|
||
messages->append(xstring("Hello World Test"));
|
||
Session->UIDisplayMessage("message.txt", "USER_INFO", messages);
|
||
}
|
||
}
|
||
catch (...) {
|
||
// 处理失败
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
// 测试路由处理器
|
||
HttpResponse TestHandler(const HttpRequest& request) {
|
||
bool creo_connected = false;
|
||
|
||
try {
|
||
pfcSession_ptr session = pfcGetCurrentSessionWithCompatibility(pfcC4Compatible);
|
||
creo_connected = (session != nullptr);
|
||
}
|
||
catch (...) {
|
||
creo_connected = false;
|
||
}
|
||
|
||
std::ostringstream json;
|
||
json << "{"
|
||
<< "\"success\": true,"
|
||
<< "\"data\": {"
|
||
<< "\"running\": " << (creo_connected ? "true" : "false") << ","
|
||
<< "\"message\": \"" << (creo_connected ? "CREOSON 与 Creo 均已启动" : "Creo 未连接") << "\""
|
||
<< "},"
|
||
<< "\"error\": null"
|
||
<< "}";
|
||
|
||
HttpResponse response;
|
||
response.body = json.str();
|
||
return response;
|
||
}
|
||
|
||
// 显示消息路由处理器
|
||
HttpResponse ShowMessageHandler(const HttpRequest& request) {
|
||
// 从查询参数获取消息
|
||
std::string message = "Default message";
|
||
size_t text_pos = request.query.find("text=");
|
||
if (text_pos != std::string::npos) {
|
||
text_pos += 5; // 跳过"text="
|
||
size_t end_pos = request.query.find("&", text_pos);
|
||
if (end_pos == std::string::npos) {
|
||
end_pos = request.query.length();
|
||
}
|
||
message = request.query.substr(text_pos, end_pos - text_pos);
|
||
}
|
||
|
||
// 设置待处理消息
|
||
{
|
||
std::lock_guard<std::mutex> lock(message_mutex);
|
||
pending_message = message;
|
||
has_pending_message = true;
|
||
}
|
||
|
||
HttpResponse response;
|
||
response.body = "{\"status\":\"ok\",\"message\":\"Message sent to Creo\"}";
|
||
return response;
|
||
}
|
||
|
||
// Creo状态检测路由处理器
|
||
HttpResponse CreoStatusHandler(const HttpRequest& request) {
|
||
CreoStatus status = CreoManager::Instance().GetCreoStatus();
|
||
|
||
std::ostringstream json;
|
||
json << "{"
|
||
<< "\"is_connected\":" << (status.is_connected ? "true" : "false") << ","
|
||
<< "\"version\":\"" << status.version << "\","
|
||
<< "\"build\":\"" << status.build << "\","
|
||
<< "\"working_directory\":\"" << status.working_directory << "\","
|
||
<< "\"session_id\":" << status.session_id
|
||
<< "}";
|
||
|
||
HttpResponse response;
|
||
response.body = json.str();
|
||
return response;
|
||
}
|
||
|
||
// 模型状态检测路由处理器
|
||
HttpResponse ModelStatusHandler(const HttpRequest& request) {
|
||
ModelStatus status = CreoManager::Instance().GetModelStatus();
|
||
|
||
std::ostringstream json;
|
||
if (status.has_model) {
|
||
json << "{"
|
||
<< "\"success\": true,"
|
||
<< "\"data\": {"
|
||
<< "\"name\": \"" << status.name << "\","
|
||
<< "\"filename\": \"" << status.filename << "\","
|
||
<< "\"type\": \"" << status.type << "\","
|
||
<< "\"software\": \"" << status.software << "\","
|
||
<< "\"version\": \"" << status.version << "\","
|
||
<< "\"connectionTime\": \"" << status.connection_time << "\","
|
||
<< "\"isAssembly\": " << (status.is_assembly ? "true" : "false") << ",";
|
||
|
||
if (status.is_assembly) {
|
||
json << "\"basicStats\": {"
|
||
<< "\"totalParts\": " << status.total_parts << ","
|
||
<< "\"assemblyLevels\": " << status.assembly_levels << ","
|
||
<< "\"fileSize\": \"" << status.file_size << "\""
|
||
<< "},";
|
||
}
|
||
|
||
json << "\"fileName\": \"" << status.filename << "\","
|
||
<< "\"sourceSoftware\": \"" << status.software << "\","
|
||
<< "\"partCount\": " << status.total_parts << ","
|
||
<< "\"assemblyLevel\": " << status.assembly_levels << ","
|
||
<< "\"connectionStatus\": \"" << status.connection_status << "\","
|
||
<< "\"openTime\": \"" << status.open_time << "\""
|
||
<< "},"
|
||
<< "\"error\": null"
|
||
<< "}";
|
||
} else {
|
||
json << "{"
|
||
<< "\"success\": false,"
|
||
<< "\"data\": null,"
|
||
<< "\"error\": \"No model is currently open\""
|
||
<< "}";
|
||
}
|
||
|
||
HttpResponse response;
|
||
response.body = json.str();
|
||
return response;
|
||
}
|
||
|
||
// 简单的JSON解析函数
|
||
std::string ExtractJsonValue(const std::string& json, const std::string& key) {
|
||
// 查找键值对 "key": "value"
|
||
std::string key_pattern = "\"" + key + "\"";
|
||
size_t key_pos = json.find(key_pattern);
|
||
|
||
if (key_pos != std::string::npos) {
|
||
// 找到冒号
|
||
size_t colon_pos = json.find(":", key_pos);
|
||
if (colon_pos != std::string::npos) {
|
||
// 跳过空格找到值的开始
|
||
size_t value_start = colon_pos + 1;
|
||
while (value_start < json.length() && (json[value_start] == ' ' || json[value_start] == '\t' || json[value_start] == '\n' || json[value_start] == '\r')) {
|
||
value_start++;
|
||
}
|
||
|
||
// 检查是否是字符串值(以双引号开始)
|
||
if (value_start < json.length() && json[value_start] == '"') {
|
||
size_t value_end = json.find('"', value_start + 1);
|
||
if (value_end != std::string::npos) {
|
||
return json.substr(value_start + 1, value_end - value_start - 1);
|
||
}
|
||
}
|
||
// 处理数字值(不以双引号开始)
|
||
else if (value_start < json.length()) {
|
||
size_t value_end = value_start;
|
||
while (value_end < json.length() &&
|
||
json[value_end] != ',' &&
|
||
json[value_end] != '}' &&
|
||
json[value_end] != ']' &&
|
||
json[value_end] != ' ' &&
|
||
json[value_end] != '\t' &&
|
||
json[value_end] != '\n' &&
|
||
json[value_end] != '\r') {
|
||
value_end++;
|
||
}
|
||
if (value_end > value_start) {
|
||
return json.substr(value_start, value_end - value_start);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return "";
|
||
}
|
||
|
||
bool ExtractJsonBool(const std::string& json, const std::string& key) {
|
||
std::regex pattern("\"" + key + "\"\s*:\s*(true|false)");
|
||
std::smatch match;
|
||
if (std::regex_search(json, match, pattern)) {
|
||
return match[1].str() == "true";
|
||
}
|
||
return false;
|
||
}
|
||
|
||
// 模型导出路由处理器
|
||
HttpResponse ExportModelHandler(const HttpRequest& request) {
|
||
if (request.method != "POST") {
|
||
HttpResponse response;
|
||
response.status_code = 405;
|
||
response.body = "{\"success\": false, \"error\": \"Method not allowed\"}";
|
||
return response;
|
||
}
|
||
|
||
// 解析JSON请求体
|
||
std::string software_type = ExtractJsonValue(request.body, "software_type");
|
||
std::string format_type = ExtractJsonValue(request.body, "format_type");
|
||
std::string export_path = ExtractJsonValue(request.body, "export_path");
|
||
|
||
// 提取options中的geom_flags - 简化处理,避免正则表达式崩溃
|
||
std::string geom_flags = "solids"; // 默认值
|
||
|
||
// 简单的字符串查找方式,避免正则表达式
|
||
size_t options_pos = request.body.find("\"options\"");
|
||
if (options_pos != std::string::npos) {
|
||
size_t start_brace = request.body.find("{", options_pos);
|
||
if (start_brace != std::string::npos) {
|
||
size_t end_brace = request.body.find("}", start_brace);
|
||
if (end_brace != std::string::npos) {
|
||
std::string options_content = request.body.substr(start_brace + 1, end_brace - start_brace - 1);
|
||
std::string extracted_geom_flags = ExtractJsonValue(options_content, "geom_flags");
|
||
if (!extracted_geom_flags.empty()) {
|
||
geom_flags = extracted_geom_flags;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 验证参数
|
||
if (software_type != "creo" || format_type != "step" || export_path.empty()) {
|
||
HttpResponse response;
|
||
response.status_code = 400;
|
||
response.body = "{\"success\": false, \"error\": \"Invalid parameters\"}";
|
||
return response;
|
||
}
|
||
|
||
// 执行导出
|
||
ExportResult result = CreoManager::Instance().ExportModelToSTEP(export_path, geom_flags);
|
||
|
||
HttpResponse response;
|
||
|
||
if (result.success) {
|
||
std::ostringstream json;
|
||
json << "{"
|
||
<< "\"success\": true,"
|
||
<< "\"data\": {"
|
||
<< "\"exportPath\": \"" << result.export_path << "\","
|
||
<< "\"fileSize\": \"" << result.file_size << "\","
|
||
<< "\"format\": \"" << result.format << "\","
|
||
<< "\"exportTime\": \"" << result.export_time << "\","
|
||
<< "\"software\": \"" << result.software << "\","
|
||
<< "\"originalFile\": \"" << result.original_file << "\","
|
||
<< "\"details\": {"
|
||
<< "\"dirname\": \"" << result.dirname << "\","
|
||
<< "\"filename\": \"" << result.filename << "\","
|
||
<< "\"creoson_response\": {"
|
||
<< "\"dirname\": \"" << result.dirname << "\","
|
||
<< "\"filename\": \"" << result.filename << "\","
|
||
<< "\"full_path\": \"" << result.export_path << "\""
|
||
<< "}}"
|
||
<< "},"
|
||
<< "\"error\": null"
|
||
<< "}";
|
||
response.body = json.str();
|
||
} else {
|
||
std::ostringstream json;
|
||
json << "{"
|
||
<< "\"success\": false,"
|
||
<< "\"data\": null,"
|
||
<< "\"error\": \"" << result.error_message << "\""
|
||
<< "}";
|
||
response.body = json.str();
|
||
response.status_code = 500;
|
||
}
|
||
|
||
return response;
|
||
}
|
||
|
||
// JSON字符串转义函数
|
||
std::string EscapeJsonString(const std::string& str) {
|
||
std::string escaped = str;
|
||
|
||
// 替换反斜杠
|
||
size_t pos = 0;
|
||
while ((pos = escaped.find("\\", pos)) != std::string::npos) {
|
||
escaped.replace(pos, 1, "\\\\");
|
||
pos += 2;
|
||
}
|
||
|
||
// 替换双引号
|
||
pos = 0;
|
||
while ((pos = escaped.find("\"", pos)) != std::string::npos) {
|
||
escaped.replace(pos, 1, "\\\"");
|
||
pos += 2;
|
||
}
|
||
|
||
// 替换换行符
|
||
pos = 0;
|
||
while ((pos = escaped.find("\n", pos)) != std::string::npos) {
|
||
escaped.replace(pos, 1, "\\n");
|
||
pos += 2;
|
||
}
|
||
|
||
// 替换制表符
|
||
pos = 0;
|
||
while ((pos = escaped.find("\t", pos)) != std::string::npos) {
|
||
escaped.replace(pos, 1, "\\t");
|
||
pos += 2;
|
||
}
|
||
|
||
return escaped;
|
||
}
|
||
|
||
// 层级分析路由处理器
|
||
HttpResponse HierarchyAnalysisHandler(const HttpRequest& request) {
|
||
HttpResponse response;
|
||
|
||
if (request.method != "POST") {
|
||
response.status_code = 405;
|
||
response.body = "{\"success\": false, \"error\": \"Method not allowed\"}";
|
||
return response;
|
||
}
|
||
|
||
try {
|
||
// 解析JSON请求
|
||
HierarchyAnalysisRequest analysis_request;
|
||
|
||
// 简单的JSON解析(参考现有的ExtractJsonValue方法)
|
||
analysis_request.software_type = ExtractJsonValue(request.body, "software_type");
|
||
analysis_request.project_name = ExtractJsonValue(request.body, "project_name");
|
||
analysis_request.include_geometry = ExtractJsonValue(request.body, "include_geometry") == "true";
|
||
|
||
// 解析max_depth参数(保持兼容性,但不实际使用)
|
||
std::string max_depth_str = ExtractJsonValue(request.body, "max_depth");
|
||
if (!max_depth_str.empty()) {
|
||
try {
|
||
analysis_request.max_depth = std::stoi(max_depth_str);
|
||
} catch (...) {
|
||
analysis_request.max_depth = 0; // 0表示无限制
|
||
}
|
||
} else {
|
||
analysis_request.max_depth = 0; // 0表示无限制
|
||
}
|
||
|
||
// 执行层级分析
|
||
HierarchyAnalysisResult result = CreoManager::Instance().AnalyzeModelHierarchy(analysis_request);
|
||
|
||
if (result.success) {
|
||
// 构建成功响应
|
||
std::ostringstream json;
|
||
json << "{"
|
||
<< "\"success\": true,"
|
||
<< "\"message\": \"" << result.message << "\","
|
||
<< "\"data\": {"
|
||
<< "\"project_name\": \"" << EscapeJsonString(result.project_name) << "\","
|
||
<< "\"total_levels\": " << result.total_levels << ","
|
||
<< "\"total_components\": " << result.total_components << ","
|
||
<< "\"hierarchy\": [";
|
||
|
||
// 构建层级数据
|
||
for (size_t level = 0; level < result.hierarchy.size(); level++) {
|
||
if (level > 0) json << ",";
|
||
json << "{"
|
||
<< "\"level\": " << level << ","
|
||
<< "\"name\": \"" << (level == 0 ? "Main Assembly" :
|
||
level == 1 ? "Sub Assembly" :
|
||
level == 2 ? "Parts" :
|
||
"Level " + std::to_string(level + 1) + " Components") << "\","
|
||
<< "\"components\": [";
|
||
|
||
for (size_t comp = 0; comp < result.hierarchy[level].size(); comp++) {
|
||
if (comp > 0) json << ",";
|
||
const ComponentInfo& component = result.hierarchy[level][comp];
|
||
json << "{"
|
||
<< "\"id\": \"" << EscapeJsonString(component.id) << "\","
|
||
<< "\"name\": \"" << EscapeJsonString(component.name) << "\","
|
||
<< "\"type\": \"" << EscapeJsonString(component.type) << "\","
|
||
<< "\"level\": " << component.level << ","
|
||
<< "\"children_count\": " << component.children_count << ","
|
||
<< "\"path\": \"" << EscapeJsonString(component.full_path) << "\","
|
||
<< "\"file_size\": \"" << EscapeJsonString(component.file_size) << "\","
|
||
<< "\"deletion_safety\": \"" << EscapeJsonString(component.deletion_safety) << "\""
|
||
<< "}";
|
||
}
|
||
|
||
json << "]}";
|
||
}
|
||
|
||
json << "],"
|
||
<< "\"deletion_recommendations\": {"
|
||
<< "\"safe_deletions\": [],"
|
||
<< "\"risky_deletions\": [";
|
||
|
||
// 构建删除建议
|
||
for (size_t i = 0; i < result.risky_deletions.size(); i++) {
|
||
if (i > 0) json << ",";
|
||
const DeletionRecommendation& rec = result.risky_deletions[i];
|
||
json << "{"
|
||
<< "\"component_id\": \"" << EscapeJsonString(rec.component_id) << "\","
|
||
<< "\"component_name\": \"" << EscapeJsonString(rec.component_name) << "\","
|
||
<< "\"level\": " << rec.level << ","
|
||
<< "\"reason\": \"" << EscapeJsonString(rec.reason) << "\","
|
||
<< "\"risk_factors\": [";
|
||
|
||
for (size_t j = 0; j < rec.risk_factors.size(); j++) {
|
||
if (j > 0) json << ",";
|
||
json << "\"" << EscapeJsonString(rec.risk_factors[j]) << "\"";
|
||
}
|
||
|
||
json << "],"
|
||
<< "\"confidence\": " << rec.confidence
|
||
<< "}";
|
||
}
|
||
|
||
json << "]"
|
||
<< "}"
|
||
<< "}"
|
||
<< "}";
|
||
|
||
response.body = json.str();
|
||
} else {
|
||
// 构建失败响应
|
||
std::ostringstream json;
|
||
json << "{"
|
||
<< "\"success\": false,"
|
||
<< "\"data\": null,"
|
||
<< "\"error\": \"" << result.error_message << "\""
|
||
<< "}";
|
||
response.body = json.str();
|
||
response.status_code = 500;
|
||
}
|
||
|
||
} catch (const std::exception& e) {
|
||
response.status_code = 500;
|
||
response.body = "{\"success\": false, \"error\": \"JSON parsing error: " + std::string(e.what()) + "\"}";
|
||
} catch (...) {
|
||
response.status_code = 500;
|
||
response.body = "{\"success\": false, \"error\": \"Unknown error during hierarchy analysis\"}";
|
||
}
|
||
|
||
return response;
|
||
}
|
||
|
||
// 层级删除路由处理器
|
||
HttpResponse HierarchyDeleteHandler(const HttpRequest& request) {
|
||
HttpResponse response;
|
||
|
||
if (request.method != "POST") {
|
||
response.status_code = 405;
|
||
response.body = "{\"success\": false, \"error\": \"Method not allowed\"}";
|
||
return response;
|
||
}
|
||
|
||
try {
|
||
// 解析JSON请求
|
||
std::string software_type = ExtractJsonValue(request.body, "software_type");
|
||
std::string project_name = ExtractJsonValue(request.body, "project_name");
|
||
std::string target_level_str = ExtractJsonValue(request.body, "target_level");
|
||
|
||
if (software_type.empty() || project_name.empty() || target_level_str.empty()) {
|
||
response.status_code = 400;
|
||
response.body = "{\"success\": false, \"error\": \"Missing required parameters: software_type, project_name, target_level\"}";
|
||
return response;
|
||
}
|
||
|
||
int target_level;
|
||
try {
|
||
target_level = std::stoi(target_level_str);
|
||
} catch (...) {
|
||
response.status_code = 400;
|
||
response.body = "{\"success\": false, \"error\": \"Invalid target_level parameter\"}";
|
||
return response;
|
||
}
|
||
|
||
// 执行层级删除
|
||
CreoManager::HierarchyDeleteResult result = CreoManager::Instance().DeleteHierarchyComponents(project_name, target_level);
|
||
|
||
if (result.success) {
|
||
// 构建成功响应
|
||
std::ostringstream json;
|
||
json << "{"
|
||
<< "\"success\": true,"
|
||
<< "\"message\": \"" << EscapeJsonString(result.message) << "\","
|
||
<< "\"data\": {"
|
||
<< "\"original_levels\": " << result.original_levels << ","
|
||
<< "\"target_level\": " << result.target_level << ","
|
||
<< "\"final_levels\": " << result.final_levels << ","
|
||
<< "\"deleted_components\": {";
|
||
|
||
// 构建删除组件数据
|
||
bool first_level = true;
|
||
for (const auto& level_pair : result.deleted_components) {
|
||
if (!first_level) json << ",";
|
||
first_level = false;
|
||
|
||
json << "\"level_" << level_pair.first << "\": [";
|
||
bool first_component = true;
|
||
for (const auto& component : level_pair.second) {
|
||
if (!first_component) json << ",";
|
||
first_component = false;
|
||
json << "\"" << EscapeJsonString(component) << "\"";
|
||
}
|
||
json << "]";
|
||
}
|
||
|
||
json << "},"
|
||
<< "\"deletion_summary\": {"
|
||
<< "\"total_deleted\": " << result.total_deleted << ","
|
||
<< "\"successful\": " << result.successful << ","
|
||
<< "\"failed\": " << result.failed
|
||
<< "}"
|
||
<< "},"
|
||
<< "\"error\": null"
|
||
<< "}";
|
||
|
||
response.body = json.str();
|
||
} else {
|
||
// 构建错误响应
|
||
std::ostringstream json;
|
||
json << "{"
|
||
<< "\"success\": false,"
|
||
<< "\"message\": \"" << EscapeJsonString(result.message) << "\","
|
||
<< "\"error\": \"" << EscapeJsonString(result.error_message) << "\""
|
||
<< "}";
|
||
|
||
response.status_code = 500;
|
||
response.body = json.str();
|
||
}
|
||
|
||
} catch (const std::exception& e) {
|
||
response.status_code = 500;
|
||
response.body = "{\"success\": false, \"error\": \"JSON parsing error: " + std::string(e.what()) + "\"}";
|
||
} catch (...) {
|
||
response.status_code = 500;
|
||
response.body = "{\"success\": false, \"error\": \"Unknown error during hierarchy deletion\"}";
|
||
}
|
||
|
||
return response;
|
||
}
|
||
|
||
|
||
extern "C" int user_initialize(
|
||
int argc,
|
||
char* argv[],
|
||
char* version,
|
||
char* build,
|
||
wchar_t errbuf[80])
|
||
{
|
||
pfcSession_ptr Session = pfcGetCurrentSessionWithCompatibility(pfcC4Compatible);
|
||
wfcWSession_ptr wSession = wfcWSession::cast(Session);
|
||
xstring info = L"New HTTP Server Starting on port 12345";
|
||
wSession->UIShowMessageDialog(info, NULL);
|
||
|
||
// 启动定时器处理消息
|
||
timer_id = SetTimer(NULL, 0, 100, TimerProc);
|
||
|
||
// 创建并启动HTTP服务器
|
||
g_http_server = std::make_unique<HttpServer>();
|
||
|
||
// 设置路由
|
||
g_http_server->SetRouteHandler("/test", TestHandler);
|
||
g_http_server->SetRouteHandler("/show_message", ShowMessageHandler);
|
||
g_http_server->SetRouteHandler("/api/status/creo", CreoStatusHandler);
|
||
g_http_server->SetRouteHandler("/api/status/model", ModelStatusHandler);
|
||
g_http_server->SetRouteHandler("/api/export/model", ExportModelHandler);
|
||
g_http_server->SetRouteHandler("/api/creo/analysis/hierarchy", HierarchyAnalysisHandler);
|
||
g_http_server->SetRouteHandler("/api/creo/hierarchy/delete", HierarchyDeleteHandler);
|
||
|
||
|
||
if (g_http_server->Start()) {
|
||
return 0;
|
||
} else {
|
||
g_http_server.reset();
|
||
return 1;
|
||
}
|
||
}
|
||
|
||
// --- OTK 出口函数 ---
|
||
// 这个函数在卸载插件或关闭 Creo 时被调用,非常重要!
|
||
extern "C" void user_terminate()
|
||
{
|
||
if (g_http_server) {
|
||
g_http_server->Stop();
|
||
g_http_server.reset();
|
||
}
|
||
if (timer_id != 0) {
|
||
KillTimer(NULL, timer_id);
|
||
timer_id = 0;
|
||
}
|
||
} |