[PyKDE] More sip on C fun!
Phil Thompson
phil at riverbankcomputing.co.uk
Sat May 31 11:56:00 BST 2003
On Saturday 31 May 2003 9:52 am, Jonathan Gardner wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> On Tuesday 20 May 2003 00:37, Phil Thompson wrote:
> > On Tuesday 20 May 2003 3:22 am, Jonathan Gardner wrote:
> > > 3) There is a callback function that I would like to use. How would I
> > > go about doing this in sip? What kind of function should I put as the
> > > callback? What kind of arguments should I expect from sip?
> > >
> > > Let's just keep it simple:
> > >
> > > The callback prototype: typedef void (*callback_func)(int);
> > >
> > > The "set callback" prototype: int set_callback(callback_func *);
> > > (And there is a corresponding release_callback() function as well, of
> > > course).
> > >
> > > What I would like to see in python:
> > >
> > > def callback(x): print x
> > > set_callback(callback)
> > >
> > > how do I get from C to Python via sip?
> >
> > You will have to store the Python callback object somewhere (remembering
> > that there may be several of them around at a time). You will have to
> > provide a C callback that is permanently installed which will find the
> > correct Python callback object and use the standard Python API to call it
> > - after having converted the C callback arguments to the appropriate
> > Python equivalents.
> >
> > Phil
>
> Okay, I gave it a go.
>
> The actual prototype for the callback is:
>
> typedef void (*PQnoticeProcessor) (void *arg, const char *message);
>
> The actual function to set the callback is:
>
> extern PQnoticeProcessor PQsetNoticeProcessor(PGconn *conn,
> PQnoticeProcessor proc,
> void *arg);
>
> 'arg' is whatever I want it to be. In this case, it is going to be a
> pointer to the "Conn" object I am wrapping.
>
> I add a member to Conn: PyObject noticeProcessor
> I make sure all the constructors set it to Py_None.
> I add the following method:
>
> void setNoticeProcessor(PyObject *np) {
> // Don't change anything if it is the same thing
> if (np == noticeProcessor)
> return;
>
> if (np == Py_None) {
> // Clear it out
> Py_DECREF(noticeProcessor);
> noticeProcessor = Py_None;
> Py_INCREF(noticeProcessor);
> PQsetNoticeProcessor(conn, NULL, NULL);
> } else {
> // Set it up
> Py_DECREF(noticeProcessor);
> noticeProcessor = np;
> Py_INCREF(noticeProcessor);
> PQsetNoticeProcessor(conn, pyNoticeProcessor, (void
> *)this); }
> }
>
> Looks pretty good, I think. Suggestions welcome, of course.
My coding style would use NULL rather than Py_None and...
void setNoticeProcessor(PyObject *np) {
Py_XINCREF(np);
Py_XDECREF(noticeProcessor);
noticeProcessor = np;
PQsetNoticeProcessor(conn, (np ? pyNoticeProcessor : NULL), (void *)this);
}
> I put this in the sip file:
>
> void setNoticeProcessor(int);
> %MemberCode
> PyObject *np;
> Conn *ptr;
>
> if (sipParseArgs(&sipArgsParsed,sipArgs,
> "mO",
> sipThisObj,sipClass_Conn,&ptr,
> &np))
> {
> if (np != Py_None && !PyCallable_Check(np)) {
> PyErr_SetString(PyExc_ValueError,
> "NoticeProcessor must be a callable or None.");
> return NULL;
> }
>
> ptr->setNoticeProcessor(np);
>
> return Py_None;
> }
> %End
>
> I try to compile it. It complains about a double declaration of
> "pyNoticeProcessor". I had to put a declaration before Conn. So I switch it
> around - declare Conn, describe pyNoticeProcessor, then describe Conn. That
> won't work either.
>
> So I move the 'pyNoticeProcessor' body into a %C++Code section in the sip
> file. The code doesn't show up anywhere in the cc files (it is declared
> outside of any class). I thought it would put the body in sippqcmodule.cc
> or something like that, which is what I really want (I think).
%C++Code outside of a class defintion should appear in the sippqcmodule file
(although I'm not sure there is an example in PyQt at the moment).
Inside a class definition, the code should appear towards the start of the
class specific generated code.
> But anyway, it compiles fine. It is only when I try to use it that it
> realizes there is no definition for pyNoticeProcessor. That is of course
> because the code wasn't put in any cc file that I could see.
>
> Any suggestions? I wanted to avoid making a new cc file manually, mostly
> because I am lazy. I am hoping there is a mechanism in sip to handle this
> sort of thing and throw it into sippqcmodule.cc.
>
> I finish this, and I will be done with the PostgreSQL interface, at least
> as far as it is reasonable to take it. I will release it to this list, and
> to the world immediately thereafter.
>
> Must sleep now... nearly 2:00 AM...
Phil
More information about the PyQt
mailing list