Re: PyArg_ParseTuple question
Mark Wooding, 14.12.2010 21:42: 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. I think it's worth mentioning here that the Cython compiler generates tightly tailored code for argument unpacking and type conversion. So unless you really want (or need) to write your code directly against Python's C-API, Cython will do a substantially better job with much less coding. Even if you have already written a major part of your code in C, it's worth considering to (re-)write the Python API wrapper parts in Cython if you need better performance. Stefan -- http://mail.python.org/mailman/listinfo/python-list
Re: PyArg_ParseTuple question
Mark Crispin nos...@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] -- http://mail.python.org/mailman/listinfo/python-list
PyArg_ParseTuple question
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. 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: static PyObject *call(PyObject *self, PyObject *args) { char *arg1, **arg2, *arg3; PyObject *arg2obj; PyObject *list = PyList_New(0); PyObject *ret = NULL; if(PyArg_ParseTuple(args, sO!s, arg1, list, arg2obj, arg3) { // grovel over arg2obj to get the number of members and make // sure they are all strings // allocate a big enough arg2 // copy the string pointers. ret = doMyThing(arg1, arg2, arg3); } PyObject_del(list); return ret; } By the way,... Python has tossed me a couple of curve balls, but all in all it's been quite reasonable. I still haven't read though the Python tutorial (I really do need to get up to speed on all the data types), but I've been able to get a tremendous amount of work done in a very short period of time. Oh, I've made it SEGV a few times, but these were all blunders in my C module, such as a C method returning self to indicate success (oops!). Python is the best development environment since LISP and SmallTalk nearly 20 years ago. Coming from me, that's quite high praise. -- Mark -- http://panda.com/mrc Democracy is two wolves and a sheep deciding what to eat for lunch. Liberty is a well-armed sheep contesting the vote. -- http://mail.python.org/mailman/listinfo/python-list