猿问

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

工具: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 次,然后显示上述错误。


慕尼黑5688855
浏览 233回答 1
1回答

回首忆惘然

报错的原因是这样的: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) {&nbsp; &nbsp; int i;&nbsp; &nbsp; for(i = 0; i < 10; i++) {&nbsp; &nbsp; &nbsp; &nbsp; printf("Printed from C thread...\n");&nbsp; &nbsp; &nbsp; &nbsp; Sleep(1000);&nbsp; &nbsp; }&nbsp; &nbsp; Py_RETURN_NONE;}
随时随地看视频慕课网APP

相关分类

Python
我要回答