341 lines
12 KiB
C++
341 lines
12 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 = pfcGetCurrentSessionWithCompatibility(pfcC4Compatible);
|
|
wfcWSession_ptr wSession = wfcWSession::cast(Session);
|
|
xstring info = ConvertStringToXstring(pending_message);
|
|
wSession->UIShowMessageDialog(info, NULL);
|
|
}
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
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;
|
|
}
|
|
|
|
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);
|
|
|
|
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;
|
|
}
|
|
} |