112 lines
3.4 KiB
C++
112 lines
3.4 KiB
C++
#include "mcp_tool.h"
|
|
#include "cadsdk.h"
|
|
|
|
namespace
|
|
{
|
|
// UTF-8 转 宽字符 (std::wstring)
|
|
std::wstring Utf8ToWString(const std::string &utf8Str)
|
|
{
|
|
if (utf8Str.empty()) return std::wstring();
|
|
|
|
// 第一次调用获取需要的宽字符缓冲区大小
|
|
int sizeNeeded = MultiByteToWideChar(CP_UTF8, 0, &utf8Str[0], (int)utf8Str.size(), NULL, 0);
|
|
std::wstring wstrTo(sizeNeeded, 0);
|
|
|
|
// 第二次调用真正进行转换
|
|
MultiByteToWideChar(CP_UTF8, 0, &utf8Str[0], (int)utf8Str.size(), &wstrTo[0], sizeNeeded);
|
|
return wstrTo;
|
|
}
|
|
|
|
std::string ReplaceTemplateArgs(std::string tpl, const nlohmann::json &args)
|
|
{
|
|
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<std::string>();
|
|
}
|
|
else if (it.value().is_boolean())
|
|
{
|
|
valueStr = it.value().get<bool>() ? "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();
|
|
}
|
|
}
|
|
return tpl;
|
|
}
|
|
}
|
|
|
|
#pragma region mcp_Tool_LispInline
|
|
nlohmann::json mcp_Tool_LispInline::Execute(const nlohmann::json &args)
|
|
{
|
|
std::string tpl = m_config["backend"].value("script_template", "");
|
|
std::string finalScript = ReplaceTemplateArgs(tpl, args) + " "; // 尾部加空格,等同于在 CAD 命令行敲回车
|
|
std::wstring wScript = Utf8ToWString(finalScript);
|
|
|
|
// 异步推送到 AutoCAD 命令行执行
|
|
acDocManager->sendStringToExecute(acDocManager->curDocument(), wScript.c_str());
|
|
|
|
return mcp_Tool_Utility::make_text_result("LISP内联指令已下发执行 (异步)");
|
|
}
|
|
#pragma endregion mcp_Tool_LispInline
|
|
|
|
#pragma region mcp_Tool_LispFile
|
|
nlohmann::json mcp_Tool_LispFile::Execute(const nlohmann::json &args)
|
|
{
|
|
std::string fileName = m_config["backend"].value("file_name", "");
|
|
std::string callTpl = m_config["backend"].value("call_template", "");
|
|
|
|
// 组装文件完整路径,并将反斜杠 \ 转换为 LISP 安全的正斜杠 /
|
|
std::string fullPath = m_lispDir + "/" + fileName;
|
|
std::replace(fullPath.begin(), fullPath.end(), '\\', '/');
|
|
|
|
// 组装前置加载命令,末尾的 nil 是为了防止文件不存在时 LISP 引擎报错弹窗
|
|
std::string loadCmd = "(load \"" + fullPath + "\" nil) ";
|
|
std::string executeCmd = ReplaceTemplateArgs(callTpl, args) + " ";
|
|
|
|
std::string finalScript = loadCmd + executeCmd;
|
|
std::wstring wScript = Utf8ToWString(finalScript);
|
|
|
|
acDocManager->sendStringToExecute(acDocManager->curDocument(), wScript.c_str());
|
|
|
|
return mcp_Tool_Utility::make_text_result("LISP外部文件已加载并下发执行 (异步)");
|
|
}
|
|
#pragma endregion mcp_Tool_LispFile
|
|
|
|
#pragma region mcp_Tool_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, "底层 DLL 工具实例已失效");
|
|
}
|
|
#pragma endregion mcp_Tool_DllProxy
|
|
|