【问题标题】:Method without return value in python c extension modulepython c扩展模块中没有返回值的方法
【发布时间】:2011-12-09 19:11:18
【问题描述】:

我正在尝试在 python 中创建一个通过并行端口发送数据的脚本。我正在用 C 语言创建自己的模块。

问题是:当我尝试执行我的模块时,python 崩溃了。没有错误,没有数据,什么都没有。它只是关闭。

这是我的模块:

#include <Python.h>
#include <sys/io.h>
#define BaseAddr 0x378

/*----------------------------------------------------------------------------------
Este es un módulo destinado a controlar el puerto paralelo.
Probablemente tenga que ser ejecutado como administrador.

Created by markmb
------------------------------------------------------------------------------------*/

static PyObject *
paralelo(PyObject *self, PyObject *args){
    int pin;
    ioperm(BaseAddr,3,1);
    if (!PyArg_ParseTuple(args, "i", &pin))
        return NULL;
    outb(pin,BaseAddr);
    ioperm(BaseAddr,3,0);
    return 1
}
PyMethodDef methods[] = {
    {"paralelo", paralelo, METH_VARARGS, "Sends data through a parallel port"},
    {NULL, NULL, 0, NULL}
};
PyMODINIT_FUNC
initparalelo(void){
    (void) Py_InitModule("paralelo", methods);
}

(它可以在没有所有 python 混乱的情况下工作) 我通过 distutils 编译它,然后在终端(使用 xubuntu)中输入:

import paralelo
while True:
    paralelo.paralelo(255)

在这里,它退出了 python,它输入了“markmb@...”

提前致谢!

【问题讨论】:

  • 我还没有在 C 中创建自己的 Python 模块,但是在你的函数 paralelo 中它应该返回 PyObject *,为什么你最后返回 1?
  • 它真的不应该返回任何东西,但我留下了这个返回值,以纪念我是否再次执行另一个模块
  • 那么如果你返回 NULL 怎么样呢?而不是 1 这是一个无效的指针。
  • 它看起来更好...但它仍然崩溃。现在,当我在我正在创建的程序中使用该模块时,它会引发错误:SystemError: error return without exception set
  • 顺便说一句,已经有一个模块,pypi.python.org/pypi/portio

标签: python c python-c-api parallel-port python-extensions


【解决方案1】:

所有 python 函数都应该返回一个 PyObject,除非它们想要引发异常,如下所述:这里 http://docs.python.org/extending/extending.html#intermezzo-errors-and-exceptions

您收到的错误消息 SystemError: error return without exception set 试图告诉您您的函数返回 NULL(=错误,引发异常),但没有通知 python 解释器您要引发什么异常。

当你不想从 python 函数返回一个值时,你让它返回 None (如果你在 python 代码中有一个运行到最后的函数或没有任何值的简单返回,就会发生同样的事情)。

在 cpython api 中,您通过返回 Py_None 对象来执行此操作,并且不要忘记增加其引用计数。为了帮助您不要忘记引用计数,有一个宏可以为您完成:http://docs.python.org/c-api/none.html#Py_RETURN_NONE

因此,一个不返回任何内容(=returning None)的函数的函数骨架看起来像这样:

static PyObject *
myfunction(PyObject *self, PyObject *args){
    if (!PyArg_ParseTuple(args, "i", ...))
        return NULL;
    /* .... */
    Py_RETURN_NONE;
}

最后,记录一下:已经有一个用于执行 ioperm/outb 调用的 python 模块:http://pypi.python.org/pypi/portio

【讨论】:

    【解决方案2】:

    向 python/c API 返回 NULL 表示发生了错误。但是由于您实际上没有设置异常,因此您会收到错误消息:

    SystemError: 没有设置异常的错误返回

    如果您尝试返回 None,请使用:

    return Py_BuildValue("");
    

    【讨论】:

    • 我使用了其他评论所说的:return Py_None,它可以工作
    • @markmb,小心!如果使用 return Py_None,则需要增加引用计数,否则会遇到麻烦。您应该使用我所拥有的,或者其他答案所拥有的 Py_RETURN_NONE 或调用 Py_IncRef(Py_None)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-10
    • 2018-10-12
    • 2011-11-16
    • 1970-01-01
    • 1970-01-01
    • 2011-03-31
    • 1970-01-01
    相关资源
    最近更新 更多