PYD 注册、Model Fragment 与 Part Fragment / PYD Registration, Model Fragments, and Part Fragments
📅 创建时间:2026-07-23
🏷️ 标签:#SAM #C++ #PYD #Fragment #Python2
📚 前置知识:01-plugin-p0-p5
📖 系列导航:总目录 · 上一篇:01-plugin-p0-p5 · 下一篇:03-python2-verified-api
PYD 在这里不是普通 Python 包,而是 SAM 宿主进程加载的原生扩展。它同时跨越动态库 ABI、Python 2 模块初始化和 SAM 对象注册三个边界。只把 Python 3 教程中的入口函数改名,无法解决宿主何时加载、Fragment 挂到哪个对象、对象由谁销毁以及模块能否安全卸载等问题。
注册链路与所有权
SAM 启动或发现插件
-> 装载 PYD 动态库
-> initExample1 注册 Initialize / Finalize
-> Initialize 创建 pyoModule 与 Fragment
-> Registrar 把能力挂到 Model 或 Part
-> 脚本通过对象路径调用 C++ 方法
-> Finalize 撤销能力并按反序销毁初始化与回收必须对称。module 和 fragment 若在回收前仍被 Python 对象、回调或后台任务引用,删除后会形成悬空指针;若重复初始化却只回收一次,则会泄漏或留下重复注册。计数参数应与宿主协议一致,不能自行解释为普通引用计数。
第3部分:PYD 的注册机制
3.1 Python 2 模块类
class Example1PytModule : public pyoModule
{
public:
Example1PytModule();
virtual void DefineConstants();
};Example1PytModule::Example1PytModule()
: pyoModule("Example1", methods, pyoModule::NO_IMPORT)
{
}3.2 初始化与回收
void Example1Initialize(int& count)
{
module = new Example1PytModule;
fragment = new SAMExample1Fragment;
++count;
}
void Example1Finalize(int& count)
{
delete fragment;
delete module;
--count;
}Python 2 风格入口:
extern "C" void initExample1(void)
{
iniPythonModuleRegistrar::Instance().Register(
Example1Initialize,
Example1Finalize);
}这也是为什么不能把 Python 3 的 PyInit_Example1 入口直接套到 SAM 上。
initExample1、模块名称和导出符号必须与宿主查找规则及二进制位数一致。Windows 上还要确认运行库、编译器 ABI 和依赖 DLL 的搜索路径。出现“模块不存在”时,应先区分文件未找到、依赖缺失、入口符号不匹配和初始化内部异常;这四类问题在界面上可能表现为同一条失败消息。
3.3 Model Fragment 与 Part Fragment
官方源码已经出现两类绑定:
| Fragment | Python 挂载位置 | 典型用途 |
|---|---|---|
ptsKModelFragment | mdb.models['Model-1'] | 模型级导入导出、ODB/VTK 功能 |
ptsKPartFragment | mdb.models[...].parts[...] | 节点单元、局部几何、参数化构件 |
Fragment 的选择表达能力属于谁。模型级操作可以访问多个 Part、分析步或输出数据库,适合导入导出和跨部件协调;Part 级操作应围绕当前部件的局部节点、单元和几何。把局部操作挂到模型虽然也能工作,却会迫使调用者重复传入 Part 名称,并削弱权限和生命周期边界。
最小验证顺序
先在副本模型中确认模块能够导入,再用只读探针检查目标对象是否出现预期方法。随后调用一个不保存、影响可观察且容易撤销的最小操作,记录调用前后的对象数量、类型和键。只有内存状态正确后,才进入另存、重新打开、导出和求解验证。
不要以 repr() 返回漂亮字符串作为成功依据,也不要从 Abaqus 同名对象推断 SAM 参数。头文件和示例源码证明符号存在,运行探针证明当前对象可调用,持久化与求解才证明功能进入有效工程链。失败的签名需要连同版本和对象状态记录,形成可复用的负面证据。
设计上的约束
跨 PYD 边界传递的数据应有明确所有权,优先使用宿主认可的标量、字符串、句柄和受控容器。不要让一侧分配的 C++ 对象由另一侧随意 delete,也不要让异常越过未知 ABI。耗时操作需要释放或配合解释器锁策略,并把结果提交回仍然有效的 Model/Part revision。
掌握本章后,应能从加载到回收画出完整注册链,判断方法应属于 Model 还是 Part,并为每个新增 Fragment 设计可复现的最小验证,而不是只确认编译通过。