spike(python): CPython 2.7.18 runs the 40250 root scripts on Android arm64
libpython2.7.a cross-builds with NDK 27.2 (API 24) after disabling HAVE_LANGINFO_H; 30 C modules built in. On a OnePlus 13 (API 36) the harness runs system.py -> prototype.RunApp() and imports the root modules with results identical to macOS (66/74; the 8 failures are stub values or dev-only scripts). py_embed_spike.py now isolates __main__ like CPythonLauncher and reports stdlib usage. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+33
-13
@@ -8,7 +8,7 @@
|
||||
| 项 | 数据 |
|
||||
| --- | --- |
|
||||
| 解释器 | CPython 2.7.6 内嵌(`extern/include/Python-2.7`、`python27.lib`) |
|
||||
| 启动 | `ScriptLib/PythonLauncher.cpp`:`CPythonLauncher::Create` 注入 `TRUE`/`FALSE` 到 `__builtin__`,然后把 `system.py` 作为 `__main__` 运行;`system.py` 替换 `__import__`,从 pack 读源码并 `compile` |
|
||||
| 启动 | `ScriptLib/PythonLauncher.cpp`:`CPythonLauncher::Create` 注入 `TRUE`/`FALSE` 到 `__builtin__`,然后把 `system.py` 作为 `__main__` 运行(`__main__` 的 `__builtins__` 是模块,不是 dict);`system.py` 替换 `__import__`,从 pack 读源码并 `compile` |
|
||||
| 脚本 | `root/*.py` 90 个(其中 74 个 `.py` 模块),`uiscript/uiscript/*.py` 94 个 |
|
||||
| 语法 | 154 个文件在 Python 2.7.18 下全部能编译;Python 3 下有 56 个编译失败;约 292 行只在 Python 2 下成立(`print` 语句、`except X, e`、`has_key`、`iteritems` 等) |
|
||||
| 语义风险 | 约 185 行在整数之间用 `/`(Python 2 是整除,Python 3 是浮点);字符串是 CP949 字节串 |
|
||||
@@ -27,12 +27,16 @@
|
||||
- 按 `CPythonLauncher::Create` 注入 `TRUE`/`FALSE`,所有 C++ 模块用返回 0 的桩代替,`pack` 用目录代替;
|
||||
- 原样运行 40250 的 `system.py`,再通过它自己的 `__pack_import` 导入全部 74 个 root 模块。
|
||||
|
||||
结果:**不改任何脚本,67/74 个模块加载成功**,引导过程一路执行到 `prototype.py` 的
|
||||
`app.Create` 等调用。剩下 7 个失败都是桩的问题,不是解释器或脚本的问题:
|
||||
结果:**不改任何脚本**,`system.py` 引导后 `prototype.py` 完整执行了 `RunApp()`:创建 MainStream、进入 logo
|
||||
阶段、加载 `UIScript/PopupDialog.py`、`app.Loop`、Destroy。之后逐个导入全部 74 个 root 模块,66 个成功。
|
||||
剩下 8 个失败都不是解释器或脚本的问题:
|
||||
|
||||
- `chr.MOTION_SKILL + 121` 这类常量需要真实整数(真实模块用 `PyModule_AddIntConstant` 提供);
|
||||
- locale 数据路径(`app.GetLocaleServiceName` 等返回值决定走哪个 locale 目录);
|
||||
- `rootlibcythonizer`、`test_affect` 是开发用脚本,40250 运行时也不加载。
|
||||
- `prototype`:已经由 `system.py` 执行过,再导入时 `RunApp` 结束触发 `SystemExit`,属正常;
|
||||
- `game`、`interfacemodule`:`chr.MOTION_SKILL + 121` 这类常量需要真实整数(真实模块用 `PyModule_AddIntConstant` 提供);
|
||||
- `introloading`、`consolemodule`:locale 数据路径(`app.GetLocaleServiceName` 等返回值决定走哪个 locale 目录);
|
||||
- `system`:只能作为 `__main__` 运行;`rootlibcythonizer`、`test_affect` 是开发用脚本,40250 运行时也不加载。
|
||||
|
||||
引导过程中脚本调用了 33 个 C++ 模块函数(`app.Create`、`wndMgr.Register`、`net.SetHandler` 等)。
|
||||
|
||||
结论:在 Python 2.7 上,40250 的脚本和导入机制可以原封不动运行;工作量集中在 C++ 模块本身。
|
||||
|
||||
@@ -71,12 +75,28 @@ Godot 这边只剩一个宿主 Control:把输入转发给 `CPythonWindowManage
|
||||
`root/*.py` 和 `uiscript/` 直接从 pack 读取,和 40250 相同。port-map 中 `Client/root` 的 3350 个函数
|
||||
全部记为 `N_A`(原样运行,无需移植),python 层剩下约 1540 个 C++ 函数要移植。
|
||||
|
||||
## 下一步:原型 2(待确认后执行)
|
||||
## Android 验证(2026-09-22,已通过)
|
||||
|
||||
1. 把 CPython 2.7.18 静态编进 `libmtgodot`,先做 macOS arm64 和 Android arm64,再做 iOS 模拟器;
|
||||
2. 在 Godot 进程里运行 `py_embed_spike.py` 的同等流程(C++ 桩模块),确认 67/74 的结果在三个平台上一致;
|
||||
3. 验收门槛:Android 和 iOS 都能加载 `system.py` 并导入 `ui.py`。如果 Android/iOS 编译在合理时间内做不出来,
|
||||
就改用方案 B,并对每处 `/` 做单独核对。
|
||||
设备:一加 13(PJZ110),Android API 36,arm64-v8a。复现:`tools/py_embed_android/build-and-run.sh`。
|
||||
|
||||
原型 2 通过之前,python 层(`Client/root`、`EterPythonLib`、`ScriptLib`、`*Module.cpp`)不开工;
|
||||
逻辑层(阶段 2)不受影响,可以并行推进。
|
||||
- **编译**:CPython 2.7.18 官方源码,用 NDK 27.2 的 `aarch64-linux-android24-clang` 交叉 configure,
|
||||
`make libpython2.7.a` 一次通过。只需要一处改动:关掉 `HAVE_LANGINFO_H`,因为 bionic 从 API 26 才声明 `nl_langinfo`。
|
||||
另外 30 个 C 模块静态编进去,包括 `posix` `math` `time` `_struct` `operator` `itertools` `_collections`
|
||||
`cStringIO` `cPickle` `_locale` `binascii` `datetime` `select` `fcntl` 等。全部编译通过,库大小 13 MB(含调试信息)。
|
||||
- **链接**:测试程序 `tools/py_embed_android/main.c` 链接 `libpython2.7.a -lm -ldl`,没有任何未定义符号。
|
||||
- **运行**:`Py_NoSiteFlag`/`Py_IgnoreEnvironmentFlag`/`Py_FrozenFlag` 启动,标准库以不压缩的 zip(8 MB)
|
||||
加入 `sys.path`,然后运行 `py_embed_spike.py`:**结果与 macOS 逐项相同**,66/74 个模块加载,失败的 8 个完全相同,
|
||||
引导期调用的 33 个 C++ 函数也完全相同。
|
||||
- **尚未验证**:
|
||||
- 这次是用 `adb shell` 运行的独立可执行文件,还没有在 APK 的 app 进程里跑过;
|
||||
- 标准库是从文件系统读的,还没有走 PCK 或 `asset_io`。
|
||||
|
||||
这两点属于集成工作,不涉及解释器本身能不能跑。
|
||||
|
||||
## 下一步
|
||||
|
||||
1. 把 CPython 2.7.18 放进 `extension/third_party/`,用我们自己的 CMake 编译(macOS / Android / iOS 共用一份源码清单和
|
||||
`pyconfig.h`),静态链接进 `libmtgodot`;
|
||||
2. `pack` 模块走 `asset_io`,标准库的纯 Python 文件放进资源包,用 `system.py` 自带的导入钩子加载;
|
||||
3. 在 APK 里跑同样的引导流程(C++ 桩模块),然后按同样方法验证 iOS;
|
||||
4. 之后 python 层才开始移植:`ScriptLib/PythonLauncher.cpp` → `EterPythonLib` 窗口系统 → `*Module.cpp`。
|
||||
|
||||
Reference in New Issue
Block a user