Re: PyArg_ParseTuple question

2010-12-15 Thread Stefan Behnel

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

2010-12-14 Thread Mark Wooding
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

2010-12-13 Thread Mark Crispin

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