Passing python list from C to python

John Machin sjmachin at lexicon.net
Wed Jul 15 08:34:31 EDT 2009


On Jul 15, 7:54 pm, hartley <hartle... at gmail.com> wrote:
> On Jul 14, 2:21 pm, John Machin <sjmac... at lexicon.net> wrote:
> > On Jul 14, 7:22 pm, hartley <hartle... at gmail.com> wrote:> > > I'm very new at wrapping Python/C, and I have run into some problems.

[snip]

/* the first telling */
> > > > statement C_embedding.buff = the_pylist ?
>
> > > > BTW C-embedding would trigger a syntax error in Python source; best to
> > > > avoid ...

/* the second telling */
> > Oh by the way, you can get away with C-embedding as a module name if
> > you are importing it from C, but importing it from Python [so that you
> > could test it independently of your C program] presents a difficulty
> > (syntax error) ... better to change it to c_embedding.
>
>
> As for what I'm reading, I'm familiar with both
>
> http://docs.python.org/c-api/
> andhttp://docs.python.org/extending/embedding.html#pure-embedding

You must have a very strange definition of familiarity! That section
has as I pointed out a complete working example of a C program that
calls a Python function with 1 or more arguments, complete with error
checking and reference counting. To me, familiarity would include
reading that program, understanding what it is doing (there are
copious explanations), compiling it, running it, then start making
changes (like I did) to do things like what you want to do.

> but i still find it hard to read this and find the proper API. The
> Python/C API reference is 162 pages!

It's a reference, not a novel. You needed no API that was not in the
sample program. What you should do is when you are going through the
example programs, look up each API in the reference manual to see what
the arguments are supposed to be, what other possibilities there are
(e.g. PyObject_CallObject 2nd arg is NULL or a tuple of your args),
what the return value is, what if anything is said about reference
counts, what similar APIs are there (e.g. a few called
PyObject_Callxxxxxxx)

> I have a second issue that I've also struggled with, namely using
> class object (don't shoot me if my terminology is off again). With the
> little toy class below, i want to instansiate it, boost it, and return
> it, similar to:
>
> s = ObjectTest()
> s.boostList()
> return s.dispList()

Let's break that down:

alist = s.dispList()
return alist

s.dispList (despite its name indicating "display") returns a reference
to a list. Your C program is going to return that to whom? The shell?

> but in C, of course.
>
> so far I have:
>
> pName = PyString_FromString("ob-test");

/* the third telling */
s/-/_/

"What I tell you three times is true". Just do it.

> pModule = PyImport_Import(pName);

You've imported the module. So far, I'm making the charitable
assumption that the lack of error checking is for brevity in your
posting, but is there in your actual code.

> pFunc = PyObject_GetAttrString(pModule,"ObjectTest");

You've obtained a reference to the class.

> if (pFunc && PyCallable_Check(pFunc)) {
>
>             printf("Callable\n");
>                 }

And if there's a problem, you'll fall through and use the dud
reference to the class??

Get into the habit NOW of doing the error checking properly, after
each API call; otherwise debugging will become a nightmare. Follow the
examples in the sample program. In this case, it is necessary only to
test for NULL, and get the correct error message displayed for that.
Checking if the returned object is callable in the same if-test clouds
the issue. Checking for callability separately is quite unnecessary --
just call the object and you'll find out then if it's not callable.

> pObj = PyObject_CallObject(pFunc,NULL);
>         if (pObj != NULL) {
>         printf("WAS NOT NULL!\n");

Again instead of printing congratulatory messages on success, put in
proper checking for failure, get the error message printed and bale
out.

> }
>
> At least this seems to work. However, as to how to actually
> instantiate and use this class the way I described, I have no idea
> which API to use.

You don't know how to instantiate the class? What do you think was the
purpose of the PyObject_CallObject() that you just did??

> Even though I've spent lots of time reading it! Do
> you have any clue here, as well?

Let's trawl through the Python equivalent of what you want to do:

s = amodule.ObjectTest()
(1) import the module
(2) get the "objectTest" attribute of the module
(3) call it, park the result in s

s.boostList()
(1) get the "boostList" attribute of s
(2) call it ... but it's a method, maybe we need to use a different
PyObject_Callxxxxxx ... no result to park.

x = s.dispList()
(1) get the "displist" attribute of s
(2) call it (see above), park result in x
(3) do something sensible with x

>
> (ob-test.py)
> class ObjectTest:
>
>         def __init__(self):
>                 self.list = []
>
>         def boostList(self):
>                 self.list.append(1)
>
>         def dispList(self):
>                 return self.list

HTH,
John



More information about the Python-list mailing list