![](/img/trans.png)
[英]SystemError: <built-in function putText> returned NULL without setting an error
[英]How to fix "SystemError: <built-in function 'name'> returned NULL without setting an error" in Python C Extension
工具:Python3.7(64 位),Visual C++ 10.0 我正在嘗試為 Python 創建一個 C 擴展。 首先,我正在測試一個簡單的 C 代碼,它打印一個字符串並在for循環中調用 Sleep() 函數。 但是,當我從 Python 對這個名為 gen_nums 的 C 函數進行簡單調用時,出現以下錯誤:
“系統錯誤:內置函數 gen_nums 返回 NULL 且未設置錯誤”
我認為問題出在 Sleep() 函數上; 刪除“Sleep(1000)”部分或將其放在“printf("Printed from C thread...\\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 次,然后顯示上述錯誤。
報錯的原因是這樣的:Python擴展函數必須有一定的C原型:
PyObject *func(PyObject *self, PyObject *args)
方法槽包含類型的函數指針
PyObject *(*)(Pyobject *, PyObject *)
舊的方法是將函數強制轉換為此指針類型以存儲到方法槽中。 顯式轉換將消除void (*)()
到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 ,即什么都沒有,但你問“為什么只有當Sleep()
在那里時它才返回NULL
。原因是“未定義的行為”。
至於如何解決這個問題,請閱讀並理解第 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;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.