我正在努力将项目的核心功能从python移植到C,但希望保留调用模块化Python组件的能力。所以我在我的项目中嵌入了python解释器。我已经到了可以在C端和Python端到另一端进行调用的位置,并且共享数据被转换并正确处理。
但是,我似乎无法覆盖我定义的Python类中的方法。相反,没有错误,但我的self
没有设置PyCFunction
。
基本示例代码如下:
component.py
class Component(object):
def my_function(self):
print("orig function")
class CompObj(Component):
def test(self):
self.my_function()
example.c
#include <Python.h>
static PyObject *my_function_override(PyObject *self, PyObject *args) {
printf("Override method %p\n", self);
return Py_None;
}
PyMethodDef override_method = {
"my_function",
(PyCFunction)my_function_override,
METH_VARARGS,
NULL
};
int main () {
wchar_t *program;
PyObject *sys_path, *module_path;
PyObject *pModule, *pCompObj, *pCompObjInst;
PyObject *cfunc, *cmeth;
program = Py_DecodeLocale("exmaple", NULL);
Py_SetProgramName(program);
Py_InitializeEx(0);
sys_path = PySys_GetObject("path");
module_path = PyUnicode_FromString("/Users/dwalker/ex");
PyList_Append(sys_path, module_path);
Py_DECREF(module_path);
if ((pModule = PyImport_ImportModule("component")) == NULL) {
printf("No Module\n");
return -1;
}
pCompObj = PyObject_GetAttrString(pModule, "CompObj");
pCompObjInst = PyObject_CallFunction(pCompObj, NULL);
cfunc = PyCFunction_New(&override_method, NULL);
cmeth = PyMethod_New(cfunc, pCompObjInst);
PyObject_SetAttrString(pCompObjInst, "my_function", cmeth);
PyObject_CallMethod(pCompObjInst, "test", NULL);
Py_Finalize();
PyMem_RawFree(program);
return 0;
}
的CMakeLists.txt
set(SRC_CORE
example.c
)
add_executable(example ${SRC_CORE})
set_property(TARGET example PROPERTY C_STANDARD 90)
find_package(PythonInterp)
find_package(PythonLibs)
include_directories(${PYTHON_INCLUDE_PATH})
target_link_libraries(example ${PYTHON_LIBRARIES})
所以,在我构建并运行之后,我得到了输出:
Override method 0x0
正在调用override方法,但实例未作为第一个self
参数传递。我假设我做错了将方法绑定到实例。对于它的价值,我还尝试了类似的执行路径,方法是通过PyInstanceMethod_New
设置方法到pCompObj
而不是实例。但无论如何,我都不确定如何正确传递self
值。