#include "cadsdk.h" #include "mcp_tool.h" #include "mcp_utils.h" namespace { bool ReplaceTemplateArgs(const std::string &_tpl, const nlohmann::json &args, std::wstring &outScript) { if (_tpl.empty()) return false; std::string tpl(_tpl); for (auto it = args.begin(); it != args.end(); ++it) { std::string placeholder = "{" + it.key() + "}"; std::string valueStr; if (it.value().is_string()) { valueStr = it.value().get(); } else if (it.value().is_boolean()) { valueStr = it.value().get() ? "T" : "nil"; // 适配 AutoLISP 的布尔逻辑 } else { valueStr = it.value().dump(); // 数字类型直接转字符串 } size_t pos = 0; while ((pos = tpl.find(placeholder, pos)) != std::string::npos) { tpl.replace(pos, placeholder.length(), valueStr); pos += valueStr.length(); } } outScript = mcp_utils::utf8ToWString(tpl); return true; } } #pragma region LispInline nlohmann::json mcp_Tool_LispInline::Execute(const nlohmann::json &args) { std::string tpl = m_config["backend"].value("script_template", ""); std::wstring finalScript; if (!ReplaceTemplateArgs(tpl, args, finalScript)) return mcp_Tool_Utility::make_error(-32603, "Script template replacement failed."); finalScript += _T(" "); // 尾部加空格,等同于在 CAD 命令行敲回车 // 异步推送到 AutoCAD 命令行执行 acDocManager->sendStringToExecute(acDocManager->curDocument(), finalScript.c_str()); return mcp_Tool_Utility::make_text_result("LISP inline command issued for execution (asynchronous)"); } #pragma endregion LispInline #pragma region LispFile nlohmann::json mcp_Tool_LispFile::Execute(const nlohmann::json &args) { fs::path filePath = mcp_utils::relative2absolute(m_config["backend"].value("file_name", "") , fs::path(m_lispDir)); if (!fs::exists(filePath)) { return mcp_Tool_Utility::make_error(-32603, "LISP file does not exist: " + filePath.string()); } std::string callTpl = m_config["backend"].value("call_template", ""); // 组装前置加载命令,末尾的 nil 是为了防止文件不存在时 LISP 引擎报错弹窗 std::wstring loadCmd = std::wstring(_T("(load \"")) + filePath.generic_wstring() + _T("\" nil) "); std::wstring executeCmd; if (!ReplaceTemplateArgs(callTpl, args, executeCmd)) { return mcp_Tool_Utility::make_error(-32603, "Script template replacement failed."); } executeCmd += _T(" "); std::wstring finalScript = loadCmd + executeCmd; acDocManager->sendStringToExecute(acDocManager->curDocument(), finalScript.c_str()); return mcp_Tool_Utility::make_text_result("LISP external file loaded and issued for execution (asynchronous)"); } #pragma endregion LispFile #pragma region DllProxy // RAII:基座销毁工具时,自动通知 DLL 释放内存,并卸载模块 mcp_Tool_DllProxy::~mcp_Tool_DllProxy() { if (m_pRealTool && m_destroyFunc) { m_destroyFunc(m_pRealTool); } if (m_hModule) { FreeLibrary(m_hModule); } } nlohmann::json mcp_Tool_DllProxy::Execute(const nlohmann::json &args) { if (m_pRealTool) { return m_pRealTool->Execute(args); // 完美转发 } return mcp_Tool_Utility::make_error(-32603, "Underlying DLL tool instance is invalid"); } #pragma endregion DllProxy