[PyKDE] More sip on C fun!

Jonathan Gardner jgardner at jonathangardner.net
Sat May 31 10:50:00 BST 2003


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

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

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

- -- 
Jonathan Gardner
jgardner at jonathangardner.net
(was jgardn at alumni.washington.edu)
Live Free, Use Linux!
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.7 (GNU/Linux)

iD8DBQE+2G1YWgwF3QvpWNwRAjkXAKDXbUUUfvmmLxpbv7P6rnU32bZsgACg2c2Q
rdEIQX5VDM969JlRtg2OXf0=
=GfLH
-----END PGP SIGNATURE-----




More information about the PyQt mailing list