add
增加了 plugin 工程
This commit is contained in:
1 parent
cf87cfe93d
commit
a7eaa8483f
11 files changed
+282
-22
No files matched your search
@@ -12,7 +12,7 @@ set(SOURCES
|
||||
"cad_mcp_frame.rc"
|
||||
"mcp_server.cpp"
|
||||
"mcp_tool.cpp"
|
||||
"mcp_ConfigParser.cpp"
|
||||
"mcp_configParser.cpp"
|
||||
"mcp_utils.cpp"
|
||||
)
|
||||
add_def_file_name(SOURCES "${PROJECT_NAME}")
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "mcp_tool.h"
|
||||
#include "mcp_utils.h"
|
||||
#include "ghc/filesystem.hpp"
|
||||
#include "rxregsvc.h"
|
||||
|
||||
#pragma region mcp_ConfigParser
|
||||
bool mcp_ConfigParser::LoadAndRegister(const std::wstring &jsonFilePath, mcp_Tools ®istry)
|
||||
@@ -50,6 +51,7 @@ bool mcp_ConfigParser::LoadAndRegister(const std::wstring &jsonFilePath, mcp_Too
|
||||
return true;
|
||||
}
|
||||
|
||||
extern "C" int acrxGetApiVersion();
|
||||
void mcp_ConfigParser::LoadDllTool(const nlohmann::json &toolConfig, const std::wstring &pluginDir, mcp_Tools ®istry)
|
||||
{
|
||||
fs::path dllPath
|
||||
@@ -59,12 +61,53 @@ void mcp_ConfigParser::LoadDllTool(const nlohmann::json &toolConfig, const std::
|
||||
|
||||
if (!fs::exists(dllPath))
|
||||
{
|
||||
AfxMessageBox(CString(_T("[MCP Server]Warning: The DLL file does not exist; the associated tools will not load!\n")) + dllPath.c_str());
|
||||
AfxMessageBox(CString(_T("[MCP Server]Warning: The DLL file does not exist, the associated tools will not load!\n")) + dllPath.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
HMODULE hMod = LoadLibrary(dllPath.c_str());
|
||||
if (!hMod) return;
|
||||
|
||||
|
||||
CString verStr;
|
||||
verStr.Format(_T("Major ver:%d, Minor ver:%d"), ARX, SUB_ARX);
|
||||
CString ver_errMsg;
|
||||
ver_errMsg.Format(
|
||||
CString(_T("[MCP Server]Error: Failed to load the DLL. "))
|
||||
+ CString(_T("Please check whether the version of the ObjectARX SDK used by "))
|
||||
+ CString("the DLL matches the current ARX version(%s).\n"), verStr );
|
||||
|
||||
if (!hMod)
|
||||
{
|
||||
AfxMessageBox(ver_errMsg);
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. 定义版本校验函数指针
|
||||
typedef int (*GetApiVersionFunc)();
|
||||
GetApiVersionFunc getVerFn = (GetApiVersionFunc)GetProcAddress(hMod, "acrxGetApiVersion");
|
||||
|
||||
// 2. 核心拦截逻辑
|
||||
if (!getVerFn)
|
||||
{
|
||||
// 连这个函数都没导出,说明根本不是合法的 ObjectARX/MCP 插件
|
||||
AfxMessageBox(CString(
|
||||
CString(_T("The ObjectARX version of the DLL could not be determined."))
|
||||
+ CString(_T("Please ensure that the acrxGetApiVersion function is exported."))
|
||||
));
|
||||
FreeLibrary(hMod);
|
||||
return;
|
||||
}
|
||||
|
||||
// 拿 DLL 编译时的 SDK 版本,和基座当前运行的 SDK 版本进行比对
|
||||
int arx_version(acrxGetApiVersion());
|
||||
int dll_version(getVerFn());
|
||||
if (arx_version != dll_version)
|
||||
{
|
||||
// 平台大版本不匹配,强行加载必定闪崩,果断踢掉!
|
||||
FreeLibrary(hMod);
|
||||
AfxMessageBox(ver_errMsg);
|
||||
return;
|
||||
}
|
||||
|
||||
typedef mcp_Tool *(*CreateFunc)();
|
||||
typedef void (*DestroyFunc)(mcp_Tool *);
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
#pragma region mcp_Tool_LispInline
|
||||
#pragma region LispInline
|
||||
nlohmann::json mcp_Tool_LispInline::Execute(const nlohmann::json &args)
|
||||
{
|
||||
std::string tpl = m_config["backend"].value("script_template", "");
|
||||
@@ -55,9 +55,9 @@ nlohmann::json mcp_Tool_LispInline::Execute(const nlohmann::json &args)
|
||||
|
||||
return mcp_Tool_Utility::make_text_result("LISP inline command issued for execution (asynchronous)");
|
||||
}
|
||||
#pragma endregion mcp_Tool_LispInline
|
||||
#pragma endregion LispInline
|
||||
|
||||
#pragma region mcp_Tool_LispFile
|
||||
#pragma region LispFile
|
||||
nlohmann::json mcp_Tool_LispFile::Execute(const nlohmann::json &args)
|
||||
{
|
||||
fs::path filePath
|
||||
@@ -86,9 +86,9 @@ nlohmann::json mcp_Tool_LispFile::Execute(const nlohmann::json &args)
|
||||
|
||||
return mcp_Tool_Utility::make_text_result("LISP external file loaded and issued for execution (asynchronous)");
|
||||
}
|
||||
#pragma endregion mcp_Tool_LispFile
|
||||
#pragma endregion LispFile
|
||||
|
||||
#pragma region mcp_Tool_DllProxy
|
||||
#pragma region DllProxy
|
||||
// RAII:基座销毁工具时,自动通知 DLL 释放内存,并卸载模块
|
||||
mcp_Tool_DllProxy::~mcp_Tool_DllProxy()
|
||||
{
|
||||
@@ -110,5 +110,5 @@ nlohmann::json mcp_Tool_DllProxy::Execute(const nlohmann::json &args)
|
||||
}
|
||||
return mcp_Tool_Utility::make_error(-32603, "Underlying DLL tool instance is invalid");
|
||||
}
|
||||
#pragma endregion mcp_Tool_DllProxy
|
||||
#pragma endregion DllProxy
|
||||
|
||||
@@ -19,6 +19,19 @@ namespace mcp_utils
|
||||
return wstrTo;
|
||||
}
|
||||
|
||||
std::string WStringToUtf8(const std::wstring &wstr)
|
||||
{
|
||||
if (wstr.empty()) return std::string();
|
||||
|
||||
// 第一次调用获取需要的 UTF-8 缓冲区大小
|
||||
int sizeNeeded = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL);
|
||||
std::string strTo(sizeNeeded, 0);
|
||||
|
||||
// 第二次调用真正进行转换
|
||||
WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), &strTo[0], sizeNeeded, NULL, NULL);
|
||||
return strTo;
|
||||
}
|
||||
|
||||
bool mcp_utils::hasFileExist(const std::wstring &filePath) { return _taccess(filePath.c_str(), 0) == 0; }
|
||||
|
||||
bool mcp_utils::hasDirExist(const std::wstring &filePath) { return _taccess(filePath.c_str(), 0) == 0; }
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
// StdAfx.cpp : source file that includes just the standard includes
|
||||
// StdAfx.pch will be the pre-compiled header
|
||||
// StdAfx.obj will contain the pre-compiled type information
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#define WINVER 0x0600
|
||||
|
||||
#pragma warning(disable: 4786)
|
||||
|
||||
//- 'DEBUG workaround' below prevents the MFC or ATL #include-s from pulling
|
||||
//- in "Afx.h" that would force the debug CRT through #pragma-s.
|
||||
#if defined(_DEBUG) && !defined(AC_FULL_DEBUG)
|
||||
#define _DEBUG_WAS_DEFINED
|
||||
#undef _DEBUG
|
||||
#pragma message ("Compiling MFC / STL / ATL header files in release mode.")
|
||||
#endif
|
||||
|
||||
#pragma pack (push, 8)
|
||||
#pragma warning(disable: 4786 4996)
|
||||
|
||||
#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
|
||||
|
||||
#include <afxwin.h> // MFC core and standard components
|
||||
#include <afxext.h> // MFC extensions
|
||||
|
||||
#ifndef _AFX_NO_OLE_SUPPORT
|
||||
#include <afxole.h> // MFC OLE classes
|
||||
#include <afxodlgs.h> // MFC OLE dialog classes
|
||||
#include <afxdisp.h> // MFC Automation classes
|
||||
#endif
|
||||
|
||||
#include <afxdtctl.h> // MFC support for Internet Explorer 4 Common Controls
|
||||
#ifndef _AFX_NO_AFXCMN_SUPPORT
|
||||
#include <afxcmn.h> // MFC support for Windows Common Controls
|
||||
#endif
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <afxdhtml.h>
|
||||
#include <afxwin.h>
|
||||
|
||||
extern HINSTANCE _hdllInstance;
|
||||
|
||||
#ifdef _DEBUG_WAS_DEFINED
|
||||
#define _DEBUG
|
||||
#undef _DEBUG_WAS_DEFINED
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(cad_mcp_plugins)
|
||||
|
||||
find_package(nlohmann_json CONFIG REQUIRED)
|
||||
find_package(ghc_filesystem CONFIG REQUIRED)
|
||||
|
||||
set(SOURCES
|
||||
"mcp_plugins.cpp"
|
||||
"stdafx.cpp"
|
||||
)
|
||||
#add_def_file_name(SOURCES "${PROJECT_NAME}")
|
||||
|
||||
add_library(${PROJECT_NAME} SHARED ${SOURCES})
|
||||
|
||||
target_precompile_headers(${PROJECT_NAME} PRIVATE StdAfx.h)
|
||||
|
||||
target_link_objectarx(${PROJECT_NAME} AECRXBASE_EXPORT)
|
||||
|
||||
target_set_name_and_suffix(${PROJECT_NAME} "${PROJECT_NAME}" ".dll")
|
||||
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE /Zc:forScope)
|
||||
|
||||
target_include_directories(${PROJECT_NAME} INTERFACE "${CMAKE_SOURCE_DIR}/inc")
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE
|
||||
nlohmann_json::nlohmann_json
|
||||
)
|
||||
@@ -0,0 +1,76 @@
|
||||
#include "cadsdk.h"
|
||||
#include "mcp_plugin_api.h"
|
||||
#include <Windows.h>
|
||||
#include "tchar.h"
|
||||
#include "rxregsvc.h"
|
||||
|
||||
#pragma comment(lib, "rxapi.lib")
|
||||
#pragma comment(linker, "/export:acrxGetApiVersion,PRIVATE")
|
||||
|
||||
class mcp_Tool_DrawCircleCpp : public mcp_Tool
|
||||
{
|
||||
public:
|
||||
virtual nlohmann::json Execute(const nlohmann::json &args) override
|
||||
{
|
||||
// 1. 从大模型传入的参数中提取坐标和半径
|
||||
double x = args.value("cx", 0.0);
|
||||
double y = args.value("cy", 0.0);
|
||||
double r = args.value("r", 100.0);
|
||||
|
||||
// 2. 获取当前活动文档
|
||||
AcApDocument* pDoc = acDocManager->curDocument();
|
||||
if (pDoc == nullptr)
|
||||
{
|
||||
return { { "error", { { "code", -32000 }, { "message", "当前没有打开的 CAD 文档" } } } };
|
||||
}
|
||||
|
||||
// 3. 极其重要:因为调用发起者是隐式窗口消息,并非标准 CAD 命令,必须显式锁文档!
|
||||
acDocManager->lockDocument(pDoc);
|
||||
AcDbDatabase* pDb = pDoc->database();
|
||||
|
||||
AcDbBlockTable* pBlockTable = nullptr;
|
||||
Acad::ErrorStatus es = pDb->getBlockTable(pBlockTable, AcDb::kForRead);
|
||||
|
||||
if (es == Acad::eOk)
|
||||
{
|
||||
AcDbBlockTableRecord* pModelSpace = nullptr;
|
||||
es = pBlockTable->getAt(ACDB_MODEL_SPACE, pModelSpace, AcDb::kForWrite);
|
||||
|
||||
if (es == Acad::eOk)
|
||||
{
|
||||
// 在底层 C++ 层面构造实体对象
|
||||
AcGePoint3d center(x, y, 0.0);
|
||||
AcGeVector3d normal(0.0, 0.0, 1.0); // Z轴法线
|
||||
AcDbCircle* pCircle = new AcDbCircle(center, normal, r);
|
||||
|
||||
// 追加到模型空间
|
||||
AcDbObjectId circleId;
|
||||
pModelSpace->appendAcDbEntity(circleId, pCircle);
|
||||
|
||||
// 释放对象
|
||||
pCircle->close();
|
||||
pModelSpace->close();
|
||||
}
|
||||
pBlockTable->close();
|
||||
}
|
||||
|
||||
// 4. 解锁文档并刷新显示
|
||||
acDocManager->unlockDocument(pDoc);
|
||||
acedUpdateDisplay();
|
||||
|
||||
// 5. 返回标准 MCP 结果,如果失败可以根据 es 的值返回 make_error
|
||||
if (es == Acad::eOk)
|
||||
{
|
||||
return mcp_Tool_Utility::make_text_result("C++底层接口已成功在模型空间生成圆形!");
|
||||
}
|
||||
else
|
||||
{
|
||||
return mcp_Tool_Utility::make_error((int)es, "ObjectARX 内部错误");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 使用宏导出 C 风格工厂函数,供基座的 LoadLibrary 解析
|
||||
EXPORT_MCP_TOOL(mcp_Tool_DrawCircleCpp, CreateDrawCircleToolCpp)
|
||||
|
||||
|
||||
Reference in new issue
Block a user