亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何修復 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 關注
  • 286 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號