2012-05-16 10 views
9

He estado tratando de aprender cómo escribir C-extensions para Python y quiero estar seguro de que entiendo cómo funciona PyArg_ParseTupleAndKeywords.¿Cómo funciona PyArg_ParseTupleAndKeywords?

Creo que el primer argumento es un puntero PyObject que apunta a una matriz de los argumentos que pasan a la función C-extension en el orden en que se pasaron. El segundo argumento es una lista de palabras clave que se pasaron, las posiciones en las que se aprobaron y, muy probablemente, algún tipo de indicador indicando en qué posición comienzan las palabras clave y la posición se vuelve irrelevante.

PyArg_ParseTupleAndKeywords continuación, utiliza su lista de palabras clave (cuarto argumento) para mapear entre los argumentos especificados con una palabra clave y tanto la cadena de formato (tercera argumento) y las direcciones de las variables de C (5 ° & + argumentos) a la que los valores apropiados deben ser copiado

¿Es correcto mi entendimiento? Cuando leo la documentación en línea, todo lo que veo son referencias a "argumentos de posición y argumentos de palabras clave", lo que me hace sentir un poco en la oscuridad. ¿Dónde está el archivo del intérprete de Python que maneja PyArg_ParseTupleAndKeywords?

Respuesta

6

¿Has leído la explicación de apertura en http://docs.python.org/c-api/arg.html? Hace un buen trabajo al explicar lo que está pasando. No vaya directamente a la referencia específica para PyArg_ParseTupleAndKeywords; asume que lees el texto anterior y no es muy útil por sí mismo.

Aunque casi lo tienes. El primer argumento es de hecho una lista de argumentos posicionales entrantes. El segundo es un mapa de argumentos entrantes de palabra clave (asignando el nombre dado de la palabra clave al valor dado). El cuarto argumento es en realidad la lista de palabras clave que su función está preparada para aceptar. Sí, el 3er argumento es la cadena de formato y el 5to y más tarde son punteros C en los que se copian los valores.

Encontrará PyArg_ParseTupleAndKeywords() en Python/getargs.c.

+1

En lugar de simplemente la documentación del API C, hay es un buen resumen legible en http://docs.python.org/2/extendiendo/extendiendo.html – timbo

2

emular lo siguiente en Python:

def keywords(a, b, foo=None, bar=None, baz=None): 
    pass 

El siguiente trabajo:

 

static PyObject *keywords(PyObject *self, PyObject *args, PyObject *kwargs) { 
    char *a; 
    char *b; 
    char *foo = NULL; 
    char *bar = NULL; 
    char *baz = NULL; 

    // Note how "a" and "b" are included in this 
    // even though they aren't supposed to be in kwargs like in python 
    static char *kwlist[] = {"a", "b", "foo", "bar", "baz", NULL}; 

    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss|sss", kwlist, &a, &b, &foo, &bar, &baz)) { 
     return NULL; 
    } 

    printf("a is %s\n", a); 
    printf("b is %s\n", b); 
    printf("foo is %s\n", foo); 
    printf("bar is %s\n", bar); 
    printf("baz is %s\n", baz); 

    Py_RETURN_NONE; 
} 
// ... 
static PyMethodDef SpamMethods[] = { 
    //... 
    {"keywords", (PyCFunction) keywords, METH_VARARGS | METH_KEYWORDS, "practice kwargs"}, 
    {NULL, NULL, 0, NULL} 

Y utilizarlo:

 
from spam import keywords 

keywords() // Fails, require a and b 
keywords('a') // fails, requires b 
keywords('a', 'b') 
keywords('a', 'b', foo='foo', bar='bar', baz='baz) 
keywords('a', 'b','foo', 'bar', 'baz') 
keywords(a='a', b='b', foo='foo', bar='bar', baz='baz') 
+0

Weird- No puedo editar. Cuando utilizas la función "palabras clave", quieres convertirla como 'PyCFunctionWithKeywords', en lugar de' PyCFunction'. –