Ah, ctypes

Lawrence D'Oliveiro ldo at geek-central.gen.new_zealand
Mon Jun 1 06:41:44 EDT 2009

I wrote some code months ago to output 1-bit-per-pixel PNG files from
Python, doing direct calls to libpng using ctypes, because PIL didn't give
me sufficient control over colour tables and pixel depths.

I thought the code was working fine. I left it aside for some months, came
back to it a week or two ago, and found it was crashing. I was creating
CFUNCTYPE objects to do callbacks to my own I/O routines, and with GDB I was
able to narrow down the crashes to the point where libpng was trying to
invoke one of my callbacks.

What had changed? I had switched my OS from Gentoo to Debian Unstable. I
chrooted back to the Gentoo system, tried my script again--still crashed.

Went back to the doc <http://docs.python.org/library/ctypes.html> and tried
the qsort callback example. Worked fine! And then I noticed this little bit:

    Important note for callback functions:

    Make sure you keep references to CFUNCTYPE objects as long as they are
    used from C code. ctypes doesn’t, and if you don’t, they may be garbage
    collected, crashing your program when a callback is made.

Yup, that was it. I changed my installation of the callbacks from

    png.png_set_write_fn \
        ct.CFUNCTYPE(None, ct.c_void_p, ct.c_void_p, ct.c_size_t)(write_data),
        ct.CFUNCTYPE(None, ct.c_void_p)(flush_write)


    cb_write_data = ct.CFUNCTYPE(None, ct.c_void_p, ct.c_void_p, ct.c_size_t)(write_data)
    cb_flush_write = ct.CFUNCTYPE(None, ct.c_void_p)(flush_write)
    png.png_set_write_fn \

and it works again.

More information about the Python-list mailing list