为了账号安全,请及时绑定邮箱和手机立即绑定

如何修复 Python C 扩展中的SystemError:

如何修复 Python C 扩展中的SystemError:

慕尼黑5688855 2021-09-28 17:51:08
工具:Python3.7(64 位),Visual C++ 10.0 我正在尝试为 Python 创建一个 C 扩展。首先,我正在测试一个简单的 C 代码,它打印一个字符串并在for循环中调用 Sleep() 函数。但是,当我从 Python 对这个名为 gen_nums 的 C 函数进行简单调用时,出现以下错误:“系统错误:内置函数 gen_nums 返回 NULL 且未设置错误”我认为问题出在 Sleep() 函数上;删除“睡眠(1000)”部分或将其放在“printf(“从C线程打印...\n”)”之前消除了这个错误。我查看了 Sleep() 的文档,但找不到任何有用的东西。代码:#include <Python.h>static void gen_nums() {    int i;    for(i = 0; i < 10; i++) {        printf("Printed from C thread...\n");        Sleep(1000);    }}static PyMethodDef gen_numsmethods[] = {    {"gen_nums", gen_nums, METH_VARARGS, "This is a threading test"},    {NULL, NULL, 0, NULL}};static struct PyModuleDef threadmod = {    PyModuleDef_HEAD_INIT,    "threadrun",    "This is a thread test module",    -1,    gen_numsmethods};PyMODINIT_FUNC PyInit_threadrun(void) {    return PyModule_Create(&threadmod);}Python调用:threadrun.gen_nums() \\ the C module is called threadrun结果应该是:“从 C 线程打印...”10 次,每条语句之间间隔 1 秒。但是,程序打印该语句 10 次,然后显示上述错误。
查看完整描述

1 回答

?
回首忆惘然

TA贡献1847条经验 获得超11个赞

报错的原因是这样的:Python扩展函数必须有一定的C原型:


PyObject *func(PyObject *self, PyObject *args)

方法槽包含类型的函数指针


PyObject *(*)(Pyobject *, PyObject *)

旧的方法是将函数强制转换为此指针类型以存储到方法槽中。显式强制转换将void (*)()消除 to的转换错误PyObject *(*)(Pyobject *, PyObject *)。转换有效,但需要显式转换。如果不存在显式强制转换,则 C 编译器必须发出诊断消息。


您的代码没有显式转换,因此您必须收到警告


{"gen_nums", gen_nums, METH_VARARGS, "This is a threading test"},

在任何情况下,如果有一个显式的 cast,该程序仍然是一个正确的程序,直到 Python 尝试调用您的函数gen_nums(),因为 Python 会这样做,就好像它的原型是


PyObject *gen_nums(PyObject *, PyObject *);

现在C 标准说,虽然到目前为止一切都很好,但从现在开始程序的行为是未定义的,因为C11 6.3.2.3:


指向一种类型函数的指针可以转换为指向另一种类型函数的指针,然后再返回;结果应与原始指针相等。如果使用转换后的指针调用类型与引用类型不兼容的函数,则行为未定义。

你的函数返回void,即什么都没有,但你问“为什么它NULL只有Sleep()在那里才返回。原因是“未定义的行为”。


至于如何解决这个问题,请阅读并理解第 1 章(共 1 章)。用 C 或 C++ 扩展 Python - 那里有很多细节,但修复这个简单函数所需的一切都在那里详细说明。如果您遇到问题,请不要继续提问但参考文档中的问题。


该函数的修复方法是将其写为


static PyObject *gen_nums(PyObject *self, PyObject *args) {

    int i;

    for(i = 0; i < 10; i++) {

        printf("Printed from C thread...\n");

        Sleep(1000);

    }

    Py_RETURN_NONE;

}


查看完整回答
反对 回复 2021-09-28
  • 1 回答
  • 0 关注
  • 232 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信