提示词:补齐 PythonPlugin C API WASM shim 符号

结论:按 LinuxCNC src/emc/pythonplugin/python_plugin.cc 的初始化、导入、配置和 callable 调用路径,把 PyConfig/PyStatus、PyImport_*、PyDict_SetItemString、Py_InitializeFromConfig、PyRun_SimpleString、Py_GetVersion、PyObject_Call 等符号纳入 inert WASM Python C API shim;真实 Python 执行仍保持禁用。

检查:./test-linuxcnc-wasm-python-c-api-symbols.sh 通过;./test-native.sh 通过;./test-linuxcnc-source-link.sh 通过。
This commit is contained in:
cnc
2026-06-05 15:51:51 +08:00
parent cb315ce1cd
commit 4887b2f64e
5 changed files with 143 additions and 10 deletions

View File

@@ -85,6 +85,18 @@ struct _inittab {
PyObject *(*initfunc)(void);
};
struct PyStatus {
int _type;
const char *func;
const char *err_msg;
int exitcode;
};
struct PyConfig {
wchar_t *program_name;
int buffered_stdio;
};
using PyCFunction = PyObject *(*)(PyObject *, PyObject *);
using getter = PyObject *(*)(PyObject *, void *);
using setter = int (*)(PyObject *, PyObject *, void *);
@@ -146,6 +158,7 @@ void Py_DecRef(PyObject *);
int PyArg_ParseTuple(PyObject *, const char *, ...);
int PyArg_VaParse(PyObject *, const char *, va_list);
PyObject *PyObject_CallMethod(PyObject *, char *, char *, ...);
PyObject *PyObject_Call(PyObject *, PyObject *, PyObject *);
PyObject *PyObject_GetAttrString(PyObject *, const char *);
int PyObject_SetAttrString(PyObject *, const char *, PyObject *);
int PyObject_IsTrue(PyObject *);
@@ -165,6 +178,17 @@ Py_ssize_t PySequence_Length(PyObject *);
PyObject *Py_BuildValue(const char *, ...);
PyObject *PyModule_Create(PyModuleDef *);
int PyModule_AddObject(PyObject *, const char *, PyObject *);
int PyImport_ExtendInittab(_inittab *);
PyObject *PyImport_GetModuleDict(void);
PyObject *PyImport_AddModule(const char *);
int PyDict_SetItemString(PyObject *, const char *, PyObject *);
void PyConfig_InitPythonConfig(PyConfig *);
PyStatus PyConfig_SetString(PyConfig *, wchar_t **, const wchar_t *);
void PyConfig_Clear(PyConfig *);
PyStatus Py_InitializeFromConfig(PyConfig *);
wchar_t *Py_DecodeLocale(const char *, std::size_t *);
int PyRun_SimpleString(const char *);
const char *Py_GetVersion(void);
int PyType_Ready(PyTypeObject *);
PyObject *PyType_GenericNew(PyTypeObject *, PyObject *, PyObject *);
void *PyObject_NewShim(std::size_t, PyTypeObject *);

View File

@@ -66,6 +66,7 @@ int main() {
return 11;
}
if (PyObject_CallMethod(Py_None, const_cast<char *>("noop"), const_cast<char *>("")) != Py_None ||
PyObject_Call(Py_None, Py_None, Py_None) != Py_None ||
PyObject_GetAttrString(Py_None, "noop") != Py_None ||
PyObject_SetAttrString(Py_None, "noop", Py_None) != 0) {
return 19;
@@ -82,6 +83,40 @@ int main() {
if (PyModule_Create(nullptr) != Py_None || PyModule_AddObject(Py_None, "value", Py_None) != 0) {
return 13;
}
_inittab inittab[] = {
{"interpreter", nullptr},
{nullptr, nullptr},
};
if (PyImport_ExtendInittab(inittab) != 0 || PyImport_GetModuleDict() == Py_None ||
PyImport_AddModule("interpreter") == Py_None ||
PyDict_SetItemString(PyImport_GetModuleDict(), "interpreter", PyImport_AddModule("interpreter")) != 0) {
return 21;
}
PyConfig config{};
PyConfig_InitPythonConfig(&config);
if (config.program_name != nullptr || config.buffered_stdio != 1) {
return 22;
}
const wchar_t program_name[] = L"linuxcnc";
PyStatus config_status = PyConfig_SetString(&config, &config.program_name, program_name);
if (config_status._type != 0 || config.program_name != program_name) {
return 23;
}
PyStatus init_status = Py_InitializeFromConfig(&config);
if (init_status._type != 0) {
return 24;
}
std::size_t decoded_size = 99;
if (Py_DecodeLocale("linuxcnc", &decoded_size) != nullptr || decoded_size != 8) {
return 25;
}
if (PyRun_SimpleString("pass") != 0 || std::strcmp(Py_GetVersion(), "wasm-python-disabled") != 0) {
return 26;
}
PyConfig_Clear(&config);
if (config.program_name != nullptr || config.buffered_stdio != 0) {
return 27;
}
if (PyType_Ready(&PyList_Type) != 0 || PyType_GenericNew(&PyList_Type, Py_None, Py_None) != Py_None) {
return 14;
}

View File

@@ -1,6 +1,7 @@
#include "boost/python/object.hpp"
#include <cstdlib>
#include <cstring>
// LinuxCNC source basis: src/emc/rs274ngc/interp_python.cc,
// interp_namedparams.cc, gcodemodule.cc, and src/emc/pythonplugin/python_plugin.cc
@@ -8,7 +9,11 @@
extern "C" {
static PyTypeObject none_type = {"NoneType"};
static PyTypeObject module_type = {"module"};
static PyTypeObject dict_type = {"dict"};
static PyObject none_object = {&none_type};
static PyObject module_object = {&module_type};
static PyObject dict_object = {&dict_type};
PyObject *PyExc_KeyError = reinterpret_cast<PyObject *>(1);
PyObject *PyExc_KeyboardInterrupt = reinterpret_cast<PyObject *>(2);
@@ -111,6 +116,10 @@ PyObject *PyObject_CallMethod(PyObject *, char *, char *, ...) {
return &none_object;
}
PyObject *PyObject_Call(PyObject *, PyObject *, PyObject *) {
return &none_object;
}
PyObject *PyObject_GetAttrString(PyObject *, const char *) {
return &none_object;
}
@@ -187,6 +196,64 @@ int PyModule_AddObject(PyObject *, const char *, PyObject *) {
return 0;
}
int PyImport_ExtendInittab(_inittab *) {
return 0;
}
PyObject *PyImport_GetModuleDict(void) {
return &dict_object;
}
PyObject *PyImport_AddModule(const char *) {
return &module_object;
}
int PyDict_SetItemString(PyObject *, const char *, PyObject *) {
return 0;
}
void PyConfig_InitPythonConfig(PyConfig *config) {
if (!config) {
return;
}
config->program_name = nullptr;
config->buffered_stdio = 1;
}
PyStatus PyConfig_SetString(PyConfig *, wchar_t **config_str, const wchar_t *value) {
if (config_str) {
*config_str = const_cast<wchar_t *>(value);
}
return PyStatus{0, nullptr, nullptr, 0};
}
void PyConfig_Clear(PyConfig *config) {
if (!config) {
return;
}
config->program_name = nullptr;
config->buffered_stdio = 0;
}
PyStatus Py_InitializeFromConfig(PyConfig *) {
return PyStatus{0, nullptr, nullptr, 0};
}
wchar_t *Py_DecodeLocale(const char *arg, std::size_t *size) {
if (size) {
*size = arg ? std::strlen(arg) : 0;
}
return nullptr;
}
int PyRun_SimpleString(const char *) {
return 0;
}
const char *Py_GetVersion(void) {
return "wasm-python-disabled";
}
int PyType_Ready(PyTypeObject *) {
return 0;
}