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:
@@ -0,0 +1,94 @@
|
||||
#include "python_host_node.h"
|
||||
|
||||
#include <godot_cpp/core/class_db.hpp>
|
||||
|
||||
#include "python_stdlib.h"
|
||||
|
||||
#ifdef MTGODOT_HAVE_PYTHON
|
||||
// Standard types only — PythonBoot.h keeps <Python-2.7/*> and the Win32 shims out of this translation
|
||||
// unit, which has to stay compilable next to godot-cpp.
|
||||
#include "platform/ScriptLib/PythonBoot.h"
|
||||
#include <string>
|
||||
#endif
|
||||
|
||||
using namespace godot;
|
||||
|
||||
namespace mtgodot {
|
||||
|
||||
#ifdef MTGODOT_HAVE_PYTHON
|
||||
|
||||
String Metin2PythonHost::start(const String &stdlib_path) {
|
||||
String path = stdlib_path;
|
||||
if (path.is_empty()) {
|
||||
path = Metin2Python::stdlib_path(false);
|
||||
if (path.is_empty()) {
|
||||
return String("python27.zip unavailable: ") + Metin2Python::last_error();
|
||||
}
|
||||
}
|
||||
std::string error;
|
||||
if (!PythonBoot::Start(path.utf8().get_data(), &error)) {
|
||||
return String::utf8(error.c_str());
|
||||
}
|
||||
return String();
|
||||
}
|
||||
|
||||
bool Metin2PythonHost::is_running() {
|
||||
return PythonBoot::IsRunning();
|
||||
}
|
||||
|
||||
String Metin2PythonHost::run_main_script(const String &command_line) {
|
||||
std::string error;
|
||||
if (!PythonBoot::RunMainScript(command_line.utf8().get_data(), &error)) {
|
||||
return String::utf8(error.c_str());
|
||||
}
|
||||
return String();
|
||||
}
|
||||
|
||||
String Metin2PythonHost::run_line(const String &source) {
|
||||
std::string error;
|
||||
if (!PythonBoot::RunLine(source.utf8().get_data(), &error)) {
|
||||
return String::utf8(error.c_str());
|
||||
}
|
||||
return String();
|
||||
}
|
||||
|
||||
void Metin2PythonHost::stop() {
|
||||
PythonBoot::Stop();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// Built without -DMTGODOT_EMBED_PYTHON=ON: the class is still registered so GDScript can tell "no
|
||||
// interpreter in this build" apart from "the interpreter failed to start".
|
||||
String Metin2PythonHost::start(const String &) {
|
||||
return String("this build has no embedded Python (-DMTGODOT_EMBED_PYTHON=ON)");
|
||||
}
|
||||
|
||||
bool Metin2PythonHost::is_running() {
|
||||
return false;
|
||||
}
|
||||
|
||||
String Metin2PythonHost::run_main_script(const String &) {
|
||||
return String("this build has no embedded Python (-DMTGODOT_EMBED_PYTHON=ON)");
|
||||
}
|
||||
|
||||
String Metin2PythonHost::run_line(const String &) {
|
||||
return String("this build has no embedded Python (-DMTGODOT_EMBED_PYTHON=ON)");
|
||||
}
|
||||
|
||||
void Metin2PythonHost::stop() {
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void Metin2PythonHost::_bind_methods() {
|
||||
ClassDB::bind_static_method("Metin2PythonHost", D_METHOD("start", "stdlib_path"),
|
||||
&Metin2PythonHost::start, DEFVAL(String()));
|
||||
ClassDB::bind_static_method("Metin2PythonHost", D_METHOD("is_running"), &Metin2PythonHost::is_running);
|
||||
ClassDB::bind_static_method("Metin2PythonHost", D_METHOD("run_main_script", "command_line"),
|
||||
&Metin2PythonHost::run_main_script, DEFVAL(String()));
|
||||
ClassDB::bind_static_method("Metin2PythonHost", D_METHOD("run_line", "source"), &Metin2PythonHost::run_line);
|
||||
ClassDB::bind_static_method("Metin2PythonHost", D_METHOD("stop"), &Metin2PythonHost::stop);
|
||||
}
|
||||
|
||||
} // namespace mtgodot
|
||||
Reference in New Issue
Block a user