feat(python): 在 app 进程里起 40250 脚本层(2P step 4,macOS)

移植 UserInterface/RunMainScript 到 platform/ScriptLib/PythonBoot:40250 把
CPythonLauncher 放在 Main() 的栈上,这里进程归 Godot,launcher 必须活过创建它的
那次调用,所以拆成 Start / RunMainScript / RunLine / Stop。37 个模块初始化函数里
只调已移植的 initpack(),system.py 因此仍停在第一个 import。

脚本报错能传回 GDScript,靠的是 platform/EterBase/Debug.cpp 实现 LogBox/LogBoxf:
ScriptLib 的 Traceback() 在 PyErr_Fetch 之后只剩这一条路,LastLogBoxMessage()
(platform/EterBase/LogBox.h)是 traceback 唯一幸存的地方。

GDScript 侧新增 Metin2PythonHost(python_host_node.{h,cpp})——唯一同时认识
godot-cpp 和 port 树的单元,PythonBoot 保持 godot-free。检查脚本
python_host_check.gd 分两段:解释器 + 标准库那段不需要 40250 的 pack,哪个平台都
能跑;system.py 那段需要 pack,没有就跳过。桌面入口 python_host_test.gd,真机入口
MT_TEST_MODE=python(导出模板不接受 --script)。

验证(macOS):标准库可 import、codec 注册表可用、sys.path 非空,system.py 停在和
ctest port.python_launcher 完全相同的 ImportError: No module named app;
ctest 27/27。Android/iOS 进程内未做,正式启动路径仍不起解释器(2V0)。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
shenlei
2026-09-23 10:43:10 +09:00
co-authored by Claude Opus 5
parent e926759ff5
commit 0a1cdf3d3e
16 changed files with 638 additions and 76 deletions
+16 -2
View File
@@ -328,14 +328,28 @@ extension/third_party/cpython-2.7.18/ # 静态库(2P 批次
macOS 上用 `force_stage=true` 跑的就是移动端那条路径:落盘、sha 一致、字节与 `res://` 相同、`.part` 不残留、
`ZIPReader` 能打开且含 `encodings/__init__.py`,重复调用不重复复制,人为弄坏副本后重新落盘。
**未完成**:真机上跑(Android/iOS 的 `user://` 沙盒路径本身没验过),随 step 4 一起;
app 的启动流程还没有调用它——解释器要到 2V0 才在进程里起来,现在只有测试调。
进程内的调用者见 step 4`Metin2PythonHost.start()` 空路径时就调 `Metin2Python.stdlib_path()`);
正式启动路径要到 2V0 才起解释器,现在只有 `MT_TEST_MODE=python` 和测试调。
`port_platform` 现在在没有 `mtpython` 时也会排除 `platform/ScriptLib/`(与 `port_logic` 同一条规则),
否则 Windows 门禁会编到 `PythonHost.cpp`
4. 两个目标平台分别验证:编译、链接无未定义符号、`Py_Initialize`、静态 C 模块逐个 `import`、在 app 进程里跑 `system.py``prototype.RunApp()`(对照结果:74 个模块中 66 个加载成功,引导期调用 33 个 C++ 函数)。
**进程内入口(2026-09-23**`extension/src/platform/ScriptLib/PythonBoot.{h,cpp}`
40250 `RunMainScript` 的移植(`audit/port-map/UserInterface/UserInterface.cpp.json`),
拆成 `Start` / `RunMainScript` / `RunLine` / `Stop`——40250 把 `CPythonLauncher` 放在 `Main()` 的栈上,
这里进程归 Godot,launcher 必须活过创建它的那次调用。37 个模块初始化函数里只调了已移植的 `initpack()`
GDScript 侧是 `Metin2PythonHost``extension/src/python_host_node.{h,cpp}`,唯一同时认识 godot-cpp 和
port 树的单元;`PythonBoot` 保持 godot-free)。脚本报错能传回 GDScript,是因为
`platform/EterBase/Debug.cpp` 实现了 `LogBox`/`LogBoxf``Traceback()``PyErr_Fetch` 之后只剩这一条路
`platform/EterBase/LogBox.h``LastLogBoxMessage()`)。
检查脚本 `project/python_host_check.gd` 分两段:解释器 + 标准库那段不需要 40250 的 pack,哪个平台都能跑;
`system.py` 那段需要 pack,没有就跳过。桌面入口 `project/python_host_test.gd`
`godot --headless --path project --script python_host_test.gd`),真机入口是
`MT_TEST_MODE=python`(导出模板不接受 `--script`)。
| 平台 | 状态 |
| --- | --- |
| macOS arm64 | step 1、2 完成:`mtpython` 静态库 + `python.embed`(39 个内建模块全部 import,标准库 codec/pickle 通过)+ `port.python_launcher``CPythonLauncher` 跑到 `system.py` 的第一个 import`system.py` 在 app 进程内未做 |
| macOS arm64 | step 1、2、3 完成,step 4 完成:`mtpython` 静态库 + `python.embed`(39 个内建模块全部 import,标准库 codec/pickle 通过)+ `port.python_launcher``CPythonLauncher` 跑到 `system.py` 的第一个 import+ **app 进程内**`python_host_test.gd` / `MT_TEST_MODE=python`):标准库可 import、codec 注册表可用,`system.py` 停在和 ctest 完全相同的 `ImportError: No module named app``prototype.RunApp()` 要等 2V0 |
| Android arm64 | step 1 完成:NDK API 24 交叉编译出 `libmtpython.a`;独立可执行文件在真机跑通(b02c49bb);APK 进程内未做。step 2 的 ScriptLib 只在 macOS 编译过 |
| iOS arm64 | step 1 完成:iphoneos arm64 编出 133 个目标文件,无 `_system`/`_fork`/`_popen` 未定义符号;真机未跑。step 2 的 ScriptLib 只在 macOS 编译过 |
| ~~Linux x86_64~~ | 不做(2026-09-23 定,见第 1 节) |