simple(?) Python C module question

Mark Crispin nospam at panda.com
Wed Nov 17 19:25:54 EST 2010


On Wed, 17 Nov 2010, Grant Edwards posted:
> Hey, it's the IMAP guy!  Get 'im!

Busted! :p

Alright, here's the full story.

As may be obvious to some, the module is to be a Python interface into 
c-client.  What may not be obvious is that this is for QA automation.  The 
consumers of this module will know Python but not necessarily C and 
certainly not c-client.  Right now the module is called cclient but that 
will certainly change.

So, I have methods such as cclient.create that in my module look like:

static PyObject *cclient_create(PyObject *self, PyObject *args)
{
     char *mailbox;
     PyObject *ret = NULL;
     if(PyArg_ParseTuple(args, "s", &mailbox))
 	ret = Py_BuildValue("i", mail_create(NULL, mailbox));
     return ret;
}

and indeed within Python
 	cclient.create("testbox")
creates "testbox" as expected.  A bunch of other methods are the same.

Now, however, I need cclient.open, and expect to do something like:

static PyObject *cclient_create(PyObject *self, PyObject *args)
{
     char *mailbox;
     MAILSTREAM *stream;
     PyObject *ret = NULL;
     if(PyArg_ParseTuple(args, "s", &mailbox) &&
        (stream = mail_open(NULL, mailbox, 0))) {
 	ret = ???;
 	// set ret to a "cclient stream" object that has "stream" as
 	// an instance variable, and a method table, presumably via
 	// PyMethodDef, for this "cclient stream" object.
     }
     return ret;
}

So, if in Python, I do something like:
 	stream = cclient.open("testbox")
 	print stream.uid(1)

I expect that to call an method like

static PyObject *cclient_create(PyObject *self, PyObject *args)
{
     long sequence;
     MAILSTREAM *stream = ???; // get stream from self
     PyObject *ret = NULL;
     if(PyArg_ParseTuple(args, "l", &sequence))
 	ret = Py_BuildValue("i", mail_uid(stream, sequence));
     return ret;
}

So, basically, what I'm missing are the two "???" things above, plus how 
to make this "cclient stream" object call mail_close(stream).

In SmallTalk or Objective C, the method table would be defined as part of 
a factory object that has a "new" factory method that in my case would 
take "stream" as an argument and set it as the instance method.  Then to 
get the stream, I'd do something like
 	stream = [self getStream];

> Have you looked at ctypes?  It's not suitable for all libraries, but
> it can often obviate the need to write any C code:
>  http://docs.python.org/release/2.6.6/library/ctypes.html#module-ctypes

Hmm.  I don't think that it helps, especially as I don't really want to 
make the consumers of this module know anything about c-client or its 
calling conventions.

Thanks for any clues...

-- 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.



More information about the Python-list mailing list