2012-02-16 25 views
19

Este es un ejemplo sencillo de la documentación de Python (http://docs.python.org/extending/extending.html):¿Cuál es la forma "correcta" de pasar un valor booleano a una extensión 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); 
} 

Si quiero pasar un parámetro booleano adicional a la función - lo que es la forma "correcta" de hacerlo?

No parece ser una opción para pasar a bool PyArg_ParseTuple(). Así que pensé en lo siguiente:

  1. leer un entero y sólo tiene que utilizar el valor (como bool es una subclase de int)
  2. PyBool_FromLong llamada() en un entero
  3. lectura y el objeto y llamar PyBool_Check () para verificar que es un bool
  4. tal vez hay una manera de conseguir cualquier tipo de variable y obtener su valor de verdad (es decir, una matriz vacía voluntad es Falsy etc.) que es lo que suele hacer la función de pitón.

¿Alguna de estas preferencias? ¿Otras opciones?

Respuesta

16

4 tal vez hay una manera de conseguir cualquier tipo de variable y obtener su valor de verdad (es decir, una matriz vacía voluntad es Falsy etc.) que es lo que la función de pitón suele hacer.

Sí: (de Python/C API Reference)

int PyObject_IsTrue(PyObject *o) 

Devuelve 1 si el objeto O se considera que es cierto, y 0 en caso contrario. Esto es equivalente a la expresión de Python no no o. En caso de error, return -1.

EDITAR. Para responder la pregunta real, creo que el enfoque 1 es correcto, porque int es realmente el tipo correspondiente en C. El enfoque 4 es bueno, pero si documenta su función como tomar un bool, no está obligado a aceptar cualquier objeto. Las comprobaciones de tipo explícitas como en 3 sin una razón están mal vistas en Python. La conversión a otro objeto Python como en 2 no ayuda a su código C.

13

Actualmente, el análisis de un número entero (como "i") es la forma aceptada de tomar un bool.

Desde Python 3.3, PyArg_ParseTuple aceptará "p" (por "predicado"), por the latest NEWS:

  • Issue #14705: La familia PyArg_Parse() de funciones ahora son compatibles con la unidad 'p' formato , que acepta un argumento "predicado booleano". Convierte cualquier valor de Python en un entero - 0 si es "falso", y 1 en caso contrario.

Tenga en cuenta que cuando se utiliza PyArg_ParseTuple con "p", el argumento debe ser un (puntero a) int, no el tipo C99 bool:

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

He estado usando esto y he encontrado que en C debo declarar las variables como 'int' (no' bool'). O, al usar múltiples bools, no se establecerán correctamente (posiblemente un problema con la diferencia de tamaños entre un 'bool' y un' int'). – szmoore

+0

@szmoore Indica que aquí utiliza un número entero en la respuesta. – kevr

+0

Sí, pero a menudo en C puede usar 'int' y' bool' de forma intercambiable, en este caso no puede. Puedo eliminar mi comentario si es superfloo. – szmoore

6

he encontrado otro enfoque:

PyObject* py_expectArgs; 
bool expectArgs; 

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

expectArgs = PyObject_IsTrue(py_expectArgs); 

En caso de una llamada de param errónea hay una excepción "auto" "argumento 1 debe ser bool, no int"

Cuestiones relacionadas