¿Cómo funciona PyArg_ParseTupleAndKeywords?

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

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

PyArg_ParseTupleAndKeywords luego usa su lista de palabras clave (4to argumento) para mapear entre los argumentos especificados con una palabra clave y tanto la cadena de formato (3er argumento) como las direcciones de las variables C (5to y + argumentos) a las que se deben copiar los valores apropiados.

¿Mi entendimiento es correcto? Cuando leo la documentación en línea, todo lo que veo son referencias a “argumentos posicionales y argumentos de palabras clave”, que me dejan un poco en la oscuridad. ¿Dónde está el archivo para el intérprete de Python que maneja PyArg_ParseTupleAndKeywords?

¿Ha leído la explicación de apertura en http://docs.python.org/c-api/arg.html ? Hace un buen trabajo explicando lo que está pasando. No vaya directamente a la referencia específica para PyArg_ParseTupleAndKeywords ; asume que has leído el texto de arriba, 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 de palabras clave entrantes (asignando un nombre de palabra clave determinado a un valor dado). El cuarto argumento es en realidad la lista de palabras clave que su función está preparada para aceptar. Sí, el tercer argumento es la cadena de formato y el quinto y posteriores son punteros C en los que se copian los valores.

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

Para emular lo siguiente en python:

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

Lo siguiente funcionará:


 palabras clave estáticas de PyObject * (PyObject * self, PyObject * args, PyObject * kwargs) {
     char * a;
     char * b;
     char * foo = NULL;
     char * bar = NULL;
     char * baz = NULL;

     // Observe cómo se incluyen "a" y "b" en este
     // Aunque no se supone que estén en kwargs como en Python
     static char * kwlist [] = {"a", "b", "foo", "bar", "baz", NULL};

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

     printf ("a es% s \ n", a);
     printf ("b es% s \ n", b);
     printf ("foo is% s \ n", foo);
     printf ("la barra es% s \ n", barra);
     printf ("baz es% s \ n", baz);

     Py_RETURN_NONE;
 }
 // ...
 PyMethodDef SpamMethods estático [] = {
     // ...
     {"keywords", (PyCFunction) keywords, METH_VARARGS |  METH_KEYWORDS, "practica kwargs"},
     {NULL, NULL, 0, NULL}

Y para usarlo:

 de palabras clave de importación de spam

 palabras clave () // Falla, requiere a y b
 palabras clave ('a') // falla, requiere b
 palabras clave ('a', 'b')
 palabras clave ('a', 'b', foo = 'foo', bar = 'bar', baz = 'baz) 
 palabras clave ('a', 'b', 'foo', 'bar', 'baz')
 palabras clave (a = 'a', b = 'b', foo = 'foo', bar = 'bar', baz = 'baz')