PyArg_ParseTuple question

Mark Wooding mdw at distorted.org.uk
Tue Dec 14 15:42:49 EST 2010


Mark Crispin <nospam at panda.com> writes:

> In a C module, I want to pick up the arguments for a Python call like:
>     module.call("string1",["string2a", "string2b", "string2c"], "string3")
> and stash these into:
> 	char *arg1;
> 	char *arg2[];
> 	char *arg3;
> All arguments are required, and we can assume that the arg2 vector is
> terminated with a null pointer.
>
> It doesn't look like PyArg_ParseTuple will do this easily; and that
> instead I have to use either the "O!" format with a PyList prototype,
> or use "O&" and write a converter.

I think the latter is probably your best bet.

> If I use "O!", at what level does it check?  In particular, does it
> just check that the argument is a list, so I can get away with
> something like:

It does the equivalent of `isinstance', so you'll accept a `list' or an
instance of any subclass of `list'.

The `O&' converter is pretty straightforward.  Something like this ought
to do.

        static int convertlist(PyObject *o, void *p)
        {
          PyObject **v;
          Py_ssize_t i, n;

          /* Could allow general sequences using PySequence_Fast */
          if (!PyList_Check(o)) return (0);

          /* Copy stuff */
          n = PyList_GET_SIZE(o);
          if ((v = PyMem_New(PyObject *, n + 1)) == 0) return (0);
          for (i = 0; i < n; i++) {
            v[i] = PyList_GET_ITEM(o, n);
            Py_INCREF(v[i]);
          }
          v[n] = 0;

          return (1);
        }

If you want to do a more complex conversion (e.g., to the individual
items) there's more work to be done.

I could have used PySequence_* functions to read the size and items, but
that makes error handling more complicated.  One could also borrow the
references from the underlying list, which would leave the underlying
storage for the vector as the only thing to free.

I ended up writing a lot of conversion functions when I was doing Python
library bindings (for a crypto library); they're generally a good thing.
I found that the trickiest thing about PyArg_ParseTuple is in making
sure that you can clean everything up even if it goes wrong half way
through.

-- [mdw]



More information about the Python-list mailing list