[pygtk] gtk threads with a C extension module and callback
Kim Novak
kim at trdlnk.com
Thu Feb 2 00:19:45 WST 2006
I am having an issue when I enable gtk threading (call
gtk.threads_init() then gtk.main()). I'm not actually running any other
threads yet but would like to, thus I have to call gtk.threads_init(). I
don't know if this is a pygtk, gtk, python issue or user ignorance.
I've narrowed this down to a small example. The python code registers a
callback with the C extension module then calls gtk.main. The C
extension module registers a glib timeout event. When the timeout occurs
the C code invokes the Python callback. It works if I don't call
gtk.threads_init() and seg faults if I do.
The source is follows the commands I use to build and install the module
and run the test:
% python setup.py build
% python setup.py install
% python test.py
------ callbackmodule.c -------
#include <Python.h>
#include <glib.h>
static PyObject *my_callback = NULL;
static int counter = 0;
/* The timeout event handler for gtk event loop */
gint
on_timeout(gpointer data)
{
PyObject *arglist;
PyObject *result;
/* Time to call the callback */
arglist = Py_BuildValue("(i)", ++counter);
result = PyEval_CallObject(my_callback, arglist);
Py_DECREF(arglist);
Py_DECREF(result);
return 1;
}
static PyObject *
set_callback(PyObject *dummy, PyObject *args)
{
PyObject *result = NULL;
PyObject *temp;
if (PyArg_ParseTuple(args, "O:set_callback", &temp)) {
if (!PyCallable_Check(temp)) {
PyErr_SetString(PyExc_TypeError, "parameter must
be callable");
return NULL;
}
Py_XINCREF(temp); /* Add a reference to new
callback */
Py_XDECREF(my_callback); /* Dispose of previous callback */
my_callback = temp; /* Remember new callback */
/* register a timeout event for every 1 sec */
g_timeout_add(1000, on_timeout, NULL);
/* Boilerplate to return "None" */
Py_INCREF(Py_None);
result = Py_None;
}
return result;
}
static PyMethodDef CallbackMethods[] = {
{"set_callback", set_callback, METH_VARARGS,
"Register a callback."},
{NULL, NULL, 0, NULL} /* Sentinel */
};
PyMODINIT_FUNC
initcallback(void)
{
(void)Py_InitModule("callback", CallbackMethods);
}
----- setup.py ------
from distutils.core import setup, Extension
module1 = Extension('callback',
include_dirs =
['/usr/include/glib-2.0/','/usr/lib/glib-2.0/include'],
libraries = ['glib-2.0'],
library_dirs = ['/usr/lib'],
sources = ['callbackmodule.c'])
setup (name = 'PackageName',
version = '1.0',
description = 'This is a demo package',
ext_modules = [module1])
---- test.py ----
import pygtk
pygtk.require("2.6")
import gtk
import callback
def test(arg):
print "test called with", arg
callback.set_callback(test)
gtk.threads_init()
gtk.main()
More information about the pygtk
mailing list