2012-02-16 4 views
19

Questo è un semplice esempio dalla documentazione python (http://docs.python.org/extending/extending.html):Qual è il modo "corretto" per passare un booleano ad un'estensione Python C?

static PyObject * 
spam_system(PyObject *self, PyObject *args) 
{ 
    const char *command; 
    int sts; 

    if (!PyArg_ParseTuple(args, "s", &command)) 
     return NULL; 
    sts = system(command); 
    return Py_BuildValue("i", sts); 
} 

Se voglio passare un parametro booleano aggiuntivo per la funzione - che cosa è il modo "corretto" di farlo?

Non sembra esserci un'opzione bool da passare a PyArg_ParseTuple(). Così ho pensato di quanto segue:

  1. leggere un intero e basta usare il valore (come bool è una sottoclasse di int)
  2. chiamata PyBool_FromLong() su un intero
  3. lettura e l'oggetto e chiamare PyBool_Check () per verificare che si tratti di un bool
  4. forse c'è un modo per ottenere qualsiasi tipo di variabile e ottenere il suo valore di verità (cioè una matrice vuota sarà falsa ecc.) che è ciò che di solito fa la funzione python.

Uno di questi preferibile? Altre opzioni?

risposta

16

4 forse c'è un modo per ottenere qualsiasi tipo di variabile e ricevere il suo valore di verità (cioè un array vuoto volontà è falsy ecc) che è quale funzione pitone solito fanno.

Sì: (da Python/C API Reference)

int PyObject_IsTrue(PyObject *o) 

Restituisce 1 se l'oggetto o è considerato per essere vero, e 0 altrimenti. Questo è equivalente all'espressione Python not not o. In caso di errore, restituisce -1.

MODIFICA. Per rispondere alla domanda vera, penso che l'approccio 1 sia corretto, perché int è realmente il tipo corrispondente in C. L'approccio 4 è buono, ma se si documenta la propria funzione come un bool, non si è obbligati ad accettare un qualsiasi oggetto. I controlli espliciti del tipo come in 3 senza una ragione sono disapprovati in Python. La conversione in un altro oggetto Python come in 2 non aiuta il tuo codice C.

13

Attualmente, l'analisi di un numero intero (come "i") è il modo accettato di assumere un valore bool.

da Python 3.3, PyArg_ParseTuple accetterà "p" (per "predicato"), per the latest NEWS:

  • Issue #14705: The() famiglia PyArg_Parse di funzioni ora supporta il formato unità 'p', che accetta un argomento "predicato booleano". Converte qualsiasi valore Python in un numero intero - 0 se è "falso" e 1 altrimenti.

Si noti che quando si utilizza PyArg_ParseTuple con "p", l'argomento deve essere un (puntatore a) int, non il tipo C99 bool:

int x; // not "bool x" 
PyArg_ParseTuple(args, kwds, "p", &x); 
+2

Sto usando questo e ho scoperto che in C devo dichiarare variabili come 'int' (non' bool'). Oppure, quando si usano più bool, non verranno impostati correttamente (probabilmente un problema con la differenza di dimensioni tra un 'bool' e un' int'). – szmoore

+0

@szmoore Si afferma che utilizza un numero intero nella risposta qui. – kevr

+0

Sì, ma spesso in C puoi usare 'int' e' bool' in modo intercambiabile, in questo caso non puoi. Posso rimuovere il mio commento se è superfluo. – szmoore

6

ho trovato un altro approccio:

PyObject* py_expectArgs; 
bool expectArgs; 

PyArg_ParseTupleAndKeywords(args, keywds, (char *)"O!", (char **)kwlist, &PyBool_Type, &py_expectArgs); 

expectArgs = PyObject_IsTrue(py_expectArgs); 

In caso di param call errata c'è l'eccezione "auto" l'argomento 1 deve essere bool, non int "