2011-12-09 14 views
6

Sto provando a creare uno script in python che invii i dati attraverso una porta parallela. Sto creando il mio modulo in linguaggio C.Metodo senza valore restituito nel modulo di estensione python

Il problema è: quando provo ad eseguire il mio modulo, python si blocca. Nessun errore, nessun dato, niente. Si chiude semplicemente.

Questo è il mio modulo:

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

(Funziona senza tutti pasticcio python) compilo attraverso distutils e poi, nel terminale (usando Xubuntu), ho messo:

import paralelo 
while True: 
    paralelo.paralelo(255) 

E qui, esce da python, mette "markmb @ ..."

Grazie in anticipo!

+0

Non ho creato il mio modulo Python in C, ma nella tua funzione parallela dove dovrebbe restituire PyObject *, perché stai restituendo 1 alla fine? – lloydm

+0

In realtà non dovrebbe restituire nulla, ma ho lasciato quel ritorno per ricordare se dovessi fare di nuovo un altro modulo – markmb

+0

Quindi, se invece restituissi NULL? Piuttosto che 1 che è un puntatore non valido. – lloydm

risposta

10

Restituendo NULL all'API python/c indica che si è verificato un errore. Ma dal momento che non hai effettivamente impostare un'eccezione si ottiene l'errore:

SystemError: error return without exception set

Se si sta tentando di restituire None, uso:

return Py_BuildValue(""); 
+0

Ho usato quello che dice l'altro commento: restituisci Py_None, e funziona – markmb

+1

@markmb, attento! Se usi return Py_None, devi incrementare il conteggio dei riferimenti altrimenti ti troverai nei guai. Dovresti usare quello che ho, o il Py_RETURN_NONE che ha l'altra risposta o chiamare Py_IncRef (Py_None) –

13

Tutte le funzioni Python dovrebbero restituire un PyObject, salvo quando voglia di sollevare un'eccezione, come spiegato: qui http://docs.python.org/extending/extending.html#intermezzo-errors-and-exceptions

il messaggio di errore che si ottiene SystemError: error return without exception set, sta cercando di dirvi che la vostra funzione restituito NULL (= errore, sollevare un'eccezione), ma non ha informato l'interprete python quello eccezione si volere Ed per crescere.

Quando non si desidera restituire un valore da una funzione python, si fa restituire None (che è la stessa cosa che accade se nel codice python si ha una funzione che gira fino alla fine o si fa un semplice ritorno senza valore).

Nella API cpython lo si fa restituendo l'oggetto Py_None e non dimenticare di incrementare il suo conto. Per aiutarti a non dimenticare il conto, c'è una macro per farlo per te: http://docs.python.org/c-api/none.html#Py_RETURN_NONE.

Quindi una funzione scheletro per una funzione che restituisce nulla (= ritorno None) si guarda qualcosa di simile:

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

Infine, per la cronaca: non v'è un modulo Python per fare l'ioperm/outb chiamate già : http://pypi.python.org/pypi/portio