简体   繁体   English

如何修复“系统错误:<built-in function 'name'> 在 Python C 扩展中返回 NULL 而不设置错误”

[英]How to fix "SystemError: <built-in function 'name'> returned NULL without setting an error" in Python C Extension

Tools: Python3.7 (64 bit), Visual C++ 10.0 I am trying to create a C extension for Python.工具:Python3.7(64 位),Visual C++ 10.0 我正在尝试为 Python 创建一个 C 扩展。 To start, I am testing a simple C code which prints a string and invokes the Sleep() function inside a for loop.首先,我正在测试一个简单的 C 代码,它打印一个字符串并在for循环中调用 Sleep() 函数。 However, when I make a simple call to this C function, named gen_nums, from Python, I get the following error:但是,当我从 Python 对这个名为 gen_nums 的 C 函数进行简单调用时,出现以下错误:

"SystemError: built-in function gen_nums returned NULL without setting an error" “系统错误:内置函数 gen_nums 返回 NULL 且未设置错误”

I think the problem is with the Sleep() function;我认为问题出在 Sleep() 函数上; deleting the "Sleep(1000)" part or placing it before "printf("Printed from C thread...\\n")" eliminates this error.删除“Sleep(1000)”部分或将其放在“printf("Printed from C thread...\\n")”之前可消除此错误。 I looked over the documentation for Sleep() but couldn't find anything useful.我查看了 Sleep() 的文档,但找不到任何有用的东西。

C Code:代码:

#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 Call: Python调用:

threadrun.gen_nums() \\ the C module is called threadrun

The result should be: "Printed from C thread..." 10 times, with a 1 second interval between each statement.结果应该是:“从 C 线程打印...”10 次,每条语句之间间隔 1 秒。

However, the program prints the statement 10 times and then displays the aforementioned error.但是,程序打印该语句 10 次,然后显示上述错误。

The reason for the error is this: Python extension functions must have a certain C prototype:报错的原因是这样的:Python扩展函数必须有一定的C原型:

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

The method slots contain function pointers of type方法槽包含类型的函数指针

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

The old way was to forcibly cast the function to this pointer type to be stored into the method slot.旧的方法是将函数强制转换为此指针类型以存储到方法槽中。 The explicit cast will silence the error of conversion of void (*)() to PyObject *(*)(Pyobject *, PyObject *) .显式转换将消除void (*)()PyObject *(*)(Pyobject *, PyObject *)的转换错误。 The conversion is valid, but needs an explicit cast.转换有效,但需要显式转换。 If an explicit cast is not there, then a C compiler must issue a diagnostics message .如果不存在显式强制转换,则 C 编译器必须发出诊断消息

Your code does not have an explicit cast, hence you must get a warning for您的代码没有显式转换,因此您必须收到警告

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

In any case, if there were an explicit cast , the program would still be a correct program up until when Python tries to invoke your function gen_nums() , because Python will do so as if its prototype were在任何情况下,如果有一个显式的 cast ,该程序仍然是一个正确的程序,直到 Python 尝试调用您的函数gen_nums() ,因为 Python 会这样做,就好像它的原型是

PyObject *gen_nums(PyObject *, PyObject *);

Now the C standard says that while everything was fine up to this point , from now on the behaviour of the program is undefined , because C11 6.3.2.3 :现在C 标准说,虽然到目前为止一切都很好,但从现在开始程序的行为未定义的,因为C11 6.3.2.3

  1. A pointer to a function of one type may be converted to a pointer to a function of another type and back again;指向一种类型函数的指针可以转换为指向另一种类型函数的指针,然后再返回; the result shall compare equal to the original pointer.结果应与原始指针相等。 If a converted pointer is used to call a function whose type is not compatible with the referenced type, the behavior is undefined.如果使用转换后的指针调用类型与引用类型不兼容的函数,则行为未定义。

Your function returns void , ie nothing at all, yet you ask "why it returns NULL only when Sleep() is in there. The reason is "undefined behaviour".你的函数返回void ,即什么都没有,但你问“为什么只有当Sleep()在那里时它才返回NULL 。原因是“未定义的行为”。


As for how to fix this , please do read and understand the Chapter 1 of 1. Extending Python with C or C++ - there are plenty of details in there, but everything needed to fix this simple function is detailed in there.至于如何解决这个问题,请阅读并理解第 1 章(共 1 章)。用 C 或 C++ 扩展 Python - 那里有很多细节,但修复这个简单函数所需的一切都在那里详细说明。 If you get stuck please do ask further questions but do refer to the documentation in questions.如果您遇到问题继续提问但参考文档中的问题。

The fix for that function would be to write it as该函数的修复方法将其写为

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;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 系统错误:<built-in function puttext> 返回 NULL 没有设置错误</built-in> - SystemError: <built-in function putText> returned NULL without setting an error python opencv '系统错误:<built-in function drawkeypoints> 在没有设置错误的情况下返回 NULL'</built-in> - python opencv 'SystemError: <built-in function drawKeypoints> returned NULL without setting an error' cv2.imwrite() 系统错误:<built-in function imwrite> 返回 NULL 没有设置错误</built-in> - cv2.imwrite() SystemError: <built-in function imwrite> returned NULL without setting an error 系统错误:<built-in function imread> 返回 NULL 没有设置错误(tkinter)</built-in> - SystemError: <built-in function imread> returned NULL without setting an error (tkinter) cv2.imread 错误:img = cv2.imread(0) 系统错误:<built-in function imread> 返回 NULL 没有设置错误</built-in> - cv2.imread error:img = cv2.imread(0) SystemError: <built-in function imread> returned NULL without setting an error <built-in function imshow>返回 NULL 而不设置错误 - <built-in function imshow> returned NULL without setting an error <built-in function imread>返回 NULL 没有设置错误</built-in> - <built-in function imread> returned NULL without setting an error 在Python3.7.0中使用scipy.signal.lfilter()时出错: <built-in function _linear_filter> 返回NULL而不设置错误 - Error using scipy.signal.lfilter() in Python3.7.0 : <built-in function _linear_filter> returned NULL without setting an error tensorflow: <built-in function AppendInt32ArrayToTensorProto> 返回NULL而不设置错误 - tensorflow: <built-in function AppendInt32ArrayToTensorProto> returned NULL without setting an error 对象检测图像文件夹读取返回<built-in function imread>返回 NULL 而不设置错误 - Object Detection Images folder read return <built-in function imread> returned NULL without setting an error
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM