Метод без возвращаемого значения в модуле расширения Python c - PullRequest
9 голосов
/ 09 декабря 2011

Я пытаюсь создать скрипт на 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);
}

(работает без всякой путаницы в питоне) Я компилирую его через distutils, а затем в терминале (используя xubuntu) добавляю:

import paralelo
while True:
    paralelo.paralelo(255)

И здесь он выходит из python, он ставит "markmb @ ..."

Заранее спасибо!

Ответы [ 2 ]

17 голосов
/ 10 декабря 2011

Все функции Python должны возвращать PyObject, кроме случаев, когда они хотят вызвать исключение, как объяснено: здесь http://docs.python.org/extending/extending.html#intermezzo-errors-and-exceptions

Сообщение об ошибке, которое вы получаете SystemError: error return without exception set, пытается сообщить вам, что ваша функция возвратила NULL (= ошибка, вызвать исключение), но не сообщала интерпретатору python, какое исключение вы хотели вызвать.

Когда вы не хотите возвращать значение из функции python, вы заставляете его возвращать None (это то же самое, что происходит, если у вас в коде python есть функция, которая выполняется до конца или выполняет простой возврат без какого-либо значения) ).

В API-интерфейсе cpython вы делаете это, возвращая объект Py_None, и не забывайте увеличивать его refcount. Чтобы помочь вам не забыть ссылку, есть макрос, который сделает это за вас: http://docs.python.org/c-api/none.html#Py_RETURN_NONE.

Таким образом, скелет функции для функции, не возвращающей ничего (= возвращающей None), выглядит примерно так:

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

Наконец, для записи: уже есть модуль python для выполнения вызовов ioperm / outb: http://pypi.python.org/pypi/portio

11 голосов
/ 09 декабря 2011

Возврат NULL в API Python / C означает, что произошла ошибка. Но так как вы фактически не установили исключение, вы получите ошибку:

SystemError: ошибка возврата без исключения установлена ​​

Если вы пытаетесь вернуть None, используйте:

return Py_BuildValue("");
...