summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohan Dahlin <jdahlin@async.com.br>2007-04-29 21:45:33 +0000
committerJohan Dahlin <johan@src.gnome.org>2007-04-29 21:45:33 +0000
commit986ca14bd42f0cae3551f5b6aa97ef5e66e9a02c (patch)
tree7df3465c83bfc758e3b0e0fb4f535f44231e863f
parentf7a7b38d5dd5de98d9bccd3e0b6d400601cd4c26 (diff)
downloadpygobject-986ca14bd42f0cae3551f5b6aa97ef5e66e9a02c.tar.gz
pygobject-986ca14bd42f0cae3551f5b6aa97ef5e66e9a02c.tar.xz
pygobject-986ca14bd42f0cae3551f5b6aa97ef5e66e9a02c.zip
Add a generic CClosure marshaller based on ffi. This makes it possible to
2007-04-29 Johan Dahlin <jdahlin@async.com.br> * README: * configure.ac: * gobject/Makefile.am: * gobject/ffi-marshaller.c: (g_value_to_ffi_type), (g_value_from_ffi_type), (g_cclosure_marshal_generic_ffi): * gobject/ffi-marshaller.h: * gobject/gobjectmodule.c: (create_signal), (init_gobject): * pygobject-2.0.pc.in: * tests/test_signal.py: * tests/testhelpermodule.c: (test1_callback), (test1_callback_swapped), (test2_callback), (test3_callback), (test4_callback), (test_float_callback), (test_double_callback), (test_string_callback), (test_object_callback), (connectcallbacks), (_wrap_connectcallbacks), (inittesthelper): Add a generic CClosure marshaller based on ffi. This makes it possible to connect to signals on PyGObjects from C. libffi is now an optional dependency Fixes #353816 (Edward Hervey) svn path=/trunk/; revision=651
-rw-r--r--ChangeLog22
-rw-r--r--README1
-rw-r--r--configure.ac15
-rw-r--r--gobject/Makefile.am6
-rw-r--r--gobject/ffi-marshaller.c194
-rw-r--r--gobject/ffi-marshaller.h31
-rw-r--r--gobject/gobjectmodule.c22
-rw-r--r--pygobject-2.0.pc.in1
-rw-r--r--tests/test_signal.py63
-rw-r--r--tests/testhelpermodule.c158
10 files changed, 499 insertions, 14 deletions
diff --git a/ChangeLog b/ChangeLog
index ddd19e8..7eeb95a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+2007-04-29 Johan Dahlin <jdahlin@async.com.br>
+
+ * README:
+ * configure.ac:
+ * gobject/Makefile.am:
+ * gobject/ffi-marshaller.c: (g_value_to_ffi_type),
+ (g_value_from_ffi_type), (g_cclosure_marshal_generic_ffi):
+ * gobject/ffi-marshaller.h:
+ * gobject/gobjectmodule.c: (create_signal), (init_gobject):
+ * pygobject-2.0.pc.in:
+ * tests/test_signal.py:
+ * tests/testhelpermodule.c: (test1_callback),
+ (test1_callback_swapped), (test2_callback), (test3_callback),
+ (test4_callback), (test_float_callback), (test_double_callback),
+ (test_string_callback), (test_object_callback), (connectcallbacks),
+ (_wrap_connectcallbacks), (inittesthelper):
+
+ Add a generic CClosure marshaller based on ffi.
+ This makes it possible to connect to signals on PyGObjects from C.
+ libffi is now an optional dependency
+ Fixes #353816 (Edward Hervey)
+
2007-04-23 Gustavo J. A. M. Carneiro <gjc@inescporto.pt>
* configure.ac: Post-release version bump.
diff --git a/README b/README
index 84b53ab..7235e13 100644
--- a/README
+++ b/README
@@ -39,6 +39,7 @@ Requirements
* C compiler (GCC and MSVC supported)
* Python 2.3.5 or higher
* Glib 2.8.0 or higher
+ * libffi (optional)
Copyright Information
=====================
diff --git a/configure.ac b/configure.ac
index a425d05..c2855c2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -127,6 +127,17 @@ AC_SUBST([pygobject_CODEGEN_DEFINES])
AS_AC_EXPAND(DATADIR, $datadir)
+dnl libffi
+AC_MSG_CHECKING(for ffi.h)
+AC_TRY_CPP([#include <ffi.h>], pygobject_ffi_h=yes, pygobject_ffi_h=no)
+if test $pygobject_ffi_h = yes; then
+ AC_DEFINE(HAVE_FFI_H,1,[Have ffi.h include file])
+ FFI_LIBS="-lffi"
+fi
+AC_MSG_RESULT([$pygobject_ffi_h])
+AM_CONDITIONAL(HAVE_LIBFFI, test "$pygobject_ffi_h" = "yes")
+AC_SUBST(FFI_LIBS)
+
dnl add required cflags ...
JH_ADD_CFLAG([-Wall])
JH_ADD_CFLAG([-std=c9x])
@@ -143,3 +154,7 @@ AC_CONFIG_FILES(
tests/Makefile
PKG-INFO)
AC_OUTPUT
+
+echo
+echo "libffi support: $pygobject_ffi_h"
+echo
diff --git a/gobject/Makefile.am b/gobject/Makefile.am
index eba8e6c..6c4f242 100644
--- a/gobject/Makefile.am
+++ b/gobject/Makefile.am
@@ -21,7 +21,7 @@ endif
_gobject_la_CFLAGS = $(GLIB_CFLAGS)
_gobject_la_LDFLAGS = $(common_ldflags) -export-symbols-regex init_gobject
-_gobject_la_LIBADD = $(GLIB_LIBS)
+_gobject_la_LIBADD = $(GLIB_LIBS) $(FFI_LIBS)
_gobject_la_SOURCES = \
gobjectmodule.c \
pygboxed.c \
@@ -40,6 +40,10 @@ _gobject_la_SOURCES = \
pygoptioncontext.c \
pygoptiongroup.c
+if HAVE_LIBFFI
+_gobject_la_SOURCES += ffi-marshaller.c
+endif
+
if PLATFORM_WIN32
_gobject_la_CFLAGS += -DPLATFORM_WIN32
endif
diff --git a/gobject/ffi-marshaller.c b/gobject/ffi-marshaller.c
new file mode 100644
index 0000000..177f7c1
--- /dev/null
+++ b/gobject/ffi-marshaller.c
@@ -0,0 +1,194 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * pygtk- Python bindings for the GTK toolkit.
+ * Copyright (C) 2007 Johan Dahlin
+ *
+ * ffi-marshaller: Generic CMarshaller using libffi
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#include <glib-object.h>
+#include <ffi.h>
+
+static ffi_type *
+g_value_to_ffi_type (const GValue *gvalue, gpointer *value)
+{
+ ffi_type *rettype = NULL;
+ GType type = g_type_fundamental (G_VALUE_TYPE (gvalue));
+ g_assert (type != G_TYPE_INVALID);
+
+ switch (type) {
+ case G_TYPE_BOOLEAN:
+ case G_TYPE_CHAR:
+ case G_TYPE_INT:
+ rettype = &ffi_type_sint;
+ *value = (gpointer)&(gvalue->data[0].v_int);
+ break;
+ case G_TYPE_UCHAR:
+ case G_TYPE_UINT:
+ rettype = &ffi_type_uint;
+ *value = (gpointer)&(gvalue->data[0].v_uint);
+ break;
+ case G_TYPE_STRING:
+ case G_TYPE_OBJECT:
+ case G_TYPE_BOXED:
+ case G_TYPE_POINTER:
+ rettype = &ffi_type_pointer;
+ *value = (gpointer)&(gvalue->data[0].v_pointer);
+ break;
+ case G_TYPE_FLOAT:
+ rettype = &ffi_type_float;
+ *value = (gpointer)&(gvalue->data[0].v_float);
+ break;
+ case G_TYPE_DOUBLE:
+ rettype = &ffi_type_double;
+ *value = (gpointer)&(gvalue->data[0].v_double);
+ break;
+ case G_TYPE_LONG:
+ rettype = &ffi_type_slong;
+ *value = (gpointer)&(gvalue->data[0].v_long);
+ break;
+ case G_TYPE_ULONG:
+ rettype = &ffi_type_ulong;
+ *value = (gpointer)&(gvalue->data[0].v_ulong);
+ break;
+ case G_TYPE_INT64:
+ rettype = &ffi_type_sint64;
+ *value = (gpointer)&(gvalue->data[0].v_int64);
+ break;
+ case G_TYPE_UINT64:
+ rettype = &ffi_type_uint64;
+ *value = (gpointer)&(gvalue->data[0].v_uint64);
+ break;
+ default:
+ rettype = &ffi_type_pointer;
+ *value = NULL;
+ g_warning ("Unsupported fundamental type: %s", g_type_name (type));
+ break;
+ }
+ return rettype;
+}
+
+static void
+g_value_from_ffi_type (GValue *gvalue, gpointer *value)
+{
+ switch (g_type_fundamental (G_VALUE_TYPE (gvalue))) {
+ case G_TYPE_INT:
+ g_value_set_int (gvalue, *(gint*)value);
+ break;
+ case G_TYPE_FLOAT:
+ g_value_set_float (gvalue, *(gfloat*)value);
+ break;
+ case G_TYPE_DOUBLE:
+ g_value_set_double (gvalue, *(gdouble*)value);
+ break;
+ case G_TYPE_BOOLEAN:
+ g_value_set_boolean (gvalue, *(gboolean*)value);
+ break;
+ case G_TYPE_STRING:
+ g_value_set_string (gvalue, *(gchar**)value);
+ break;
+ case G_TYPE_CHAR:
+ g_value_set_char (gvalue, *(gchar*)value);
+ break;
+ case G_TYPE_UCHAR:
+ g_value_set_uchar (gvalue, *(guchar*)value);
+ break;
+ case G_TYPE_UINT:
+ g_value_set_uint (gvalue, *(guint*)value);
+ break;
+ case G_TYPE_POINTER:
+ g_value_set_pointer (gvalue, *(gpointer*)value);
+ break;
+ case G_TYPE_LONG:
+ g_value_set_long (gvalue, *(glong*)value);
+ break;
+ case G_TYPE_ULONG:
+ g_value_set_ulong (gvalue, *(gulong*)value);
+ break;
+ case G_TYPE_INT64:
+ g_value_set_int64 (gvalue, *(gint64*)value);
+ break;
+ case G_TYPE_UINT64:
+ g_value_set_uint64 (gvalue, *(guint64*)value);
+ break;
+ case G_TYPE_BOXED:
+ g_value_set_boxed (gvalue, *(gpointer*)value);
+ break;
+ default:
+ g_warning ("Unsupported fundamental type: %s",
+ g_type_name (g_type_fundamental (G_VALUE_TYPE (gvalue))));
+ }
+
+}
+
+void
+g_cclosure_marshal_generic_ffi (GClosure *closure,
+ GValue *return_gvalue,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data)
+{
+ ffi_type *rtype;
+ void *rvalue;
+ int n_args;
+ ffi_type **atypes;
+ void **args;
+ int i;
+ ffi_cif cif;
+ GCClosure *cc = (GCClosure*) closure;
+
+ if (return_gvalue && G_VALUE_TYPE (return_gvalue))
+ {
+ rtype = g_value_to_ffi_type (return_gvalue, &rvalue);
+ }
+ else
+ {
+ rtype = &ffi_type_void;
+ }
+
+ rvalue = g_alloca (MAX (rtype->size, sizeof (ffi_arg)));
+
+ n_args = n_param_values + 1;
+ atypes = g_alloca (sizeof (ffi_type *) * n_args);
+ args = g_alloca (sizeof (gpointer) * n_args);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ atypes[n_args-1] = g_value_to_ffi_type (param_values + 0,
+ &args[n_args-1]);
+ atypes[0] = &ffi_type_pointer;
+ args[0] = &closure->data;
+ }
+ else
+ {
+ atypes[0] = g_value_to_ffi_type (param_values + 0, &args[0]);
+ atypes[n_args-1] = &ffi_type_pointer;
+ args[n_args-1] = &closure->data;
+ }
+
+ for (i = 1; i < n_args - 1; i++)
+ atypes[i] = g_value_to_ffi_type (param_values + i, &args[i]);
+
+ if (ffi_prep_cif (&cif, FFI_DEFAULT_ABI, n_args, rtype, atypes) != FFI_OK)
+ return;
+
+ ffi_call (&cif, marshal_data ? marshal_data : cc->callback, rvalue, args);
+
+ if (return_gvalue && G_VALUE_TYPE (return_gvalue))
+ g_value_from_ffi_type (return_gvalue, rvalue);
+}
diff --git a/gobject/ffi-marshaller.h b/gobject/ffi-marshaller.h
new file mode 100644
index 0000000..81404b0
--- /dev/null
+++ b/gobject/ffi-marshaller.h
@@ -0,0 +1,31 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * pygtk- Python bindings for the GTK toolkit.
+ * Copyright (C) 2007 Johan Dahlin
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#ifndef _FFI_MARSHALLER_H_
+#define _FFI_MARSHALLER_H_
+
+void g_cclosure_marshal_generic_ffi (GClosure *closure,
+ GValue *return_gvalue,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data);
+
+#endif /* _FFI_MARSHALLER_H_ */
diff --git a/gobject/gobjectmodule.c b/gobject/gobjectmodule.c
index 32256a6..8316a20 100644
--- a/gobject/gobjectmodule.c
+++ b/gobject/gobjectmodule.c
@@ -28,6 +28,13 @@
#include "pythread.h"
#include <gobject/gvaluecollector.h>
+#ifdef HAVE_FFI_H
+#include "ffi-marshaller.h"
+static GSignalCMarshaller marshal_generic = g_cclosure_marshal_generic_ffi;
+#else
+static GSignalCMarshaller marshal_generic = 0;
+#endif
+
static PyObject *gerror_exc = NULL;
static gboolean use_gil_state_api = FALSE;
static PyObject *_pyg_signal_accumulator_true_handled_func;
@@ -594,7 +601,7 @@ create_signal (GType instance_type, const gchar *signal_name, PyObject *tuple)
signal_id = g_signal_newv(signal_name, instance_type, signal_flags,
pyg_signal_class_closure_get(),
accumulator, accum_data,
- (GSignalCMarshaller)0,
+ marshal_generic,
return_type, n_params, param_types);
g_free(param_types);
@@ -3452,7 +3459,7 @@ struct _PyGObject_Functions pygobject_api_functions = {
DL_EXPORT(void)
init_gobject(void)
{
- PyObject *m, *d, *o, *tuple;
+ PyObject *m, *d, *o, *tuple, *features;
PyObject *descr;
PyObject *warning;
@@ -3556,7 +3563,16 @@ init_gobject(void)
PyDict_SetItemString(d, "_PyGObject_API",
o=PyCObject_FromVoidPtr(&pygobject_api_functions,NULL));
Py_DECREF(o);
-
+
+
+ /* features */
+ features = PyDict_New();
+#ifdef HAVE_FFI_H
+ PyDict_SetItemString(features, "generic-c-marshaller", Py_True);
+#endif
+ PyDict_SetItemString(d, "features", features);
+ Py_DECREF(features);
+
/* some constants */
PyModule_AddIntConstant(m, "SIGNAL_RUN_FIRST", G_SIGNAL_RUN_FIRST);
PyModule_AddIntConstant(m, "SIGNAL_RUN_LAST", G_SIGNAL_RUN_LAST);
diff --git a/pygobject-2.0.pc.in b/pygobject-2.0.pc.in
index a4d3fbc..5e29935 100644
--- a/pygobject-2.0.pc.in
+++ b/pygobject-2.0.pc.in
@@ -15,4 +15,5 @@ Name: PyGObject
Description: Python bindings for GObject
Requires: gobject-2.0
Version: @VERSION@
+Libs: -L${libdir} @FFI_LIBS@
Cflags: -I${pygtkincludedir}
diff --git a/tests/test_signal.py b/tests/test_signal.py
index d22281e..99bb45b 100644
--- a/tests/test_signal.py
+++ b/tests/test_signal.py
@@ -3,7 +3,7 @@
import gc
import unittest
-from common import gobject
+from common import gobject, testhelper
class C(gobject.GObject):
__gsignals__ = { 'my_signal': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
@@ -303,5 +303,66 @@ class TestSigProp(unittest.TestCase):
obj = SigPropClass()
self.failIf(obj.signal_emission_failed)
+f = gobject.SIGNAL_RUN_FIRST
+l = gobject.SIGNAL_RUN_LAST
+float = gobject.TYPE_FLOAT
+double = gobject.TYPE_DOUBLE
+uint = gobject.TYPE_UINT
+ulong = gobject.TYPE_ULONG
+
+class CM(gobject.GObject):
+ __gsignals__ = dict(
+ test1=(f, None, ()),
+ test2=(l, None, (str,)),
+ test3=(l, int, (double,)),
+ test4=(f, None, (bool, long, float, double, int, uint, ulong)),
+ test_float=(l, float, (float,)),
+ test_double=(l, double, (double, )),
+ test_string=(l, str, (str, )),
+ test_object=(l, object, (object, )),
+ )
+
+class _TestCMarshaller:
+ def setUp(self):
+ self.obj = CM()
+ testhelper.connectcallbacks(self.obj)
+
+ def testTest1(self):
+ self.obj.emit("test1")
+
+ def testTest2(self):
+ self.obj.emit("test2", "string")
+
+ def testTest3(self):
+ rv = self.obj.emit("test3", 42.0)
+ self.assertEqual(rv, 20)
+
+ def testTest4(self):
+ self.obj.emit("test4", True, 10L, 3.14, 1.78, 20, 30L, 31L)
+
+ def testTestReturnFloat(self):
+ rv = self.obj.emit("test-float", 1.234)
+ self.failUnless(rv >= 1.233999 and rv <= 1.2400001, rv)
+
+ def testTestReturnDouble(self):
+ rv = self.obj.emit("test-double", 1.234)
+ self.assertEqual(rv, 1.234)
+
+ def testTestReturnString(self):
+ rv = self.obj.emit("test-string", "str")
+ self.assertEqual(rv, "str")
+
+ def testTestReturnObject(self):
+ rv = self.obj.emit("test-object", self)
+ self.assertEqual(rv, self)
+
+if 'generic-c-marshaller' in gobject.features:
+ class TestCMarshaller(_TestCMarshaller, unittest.TestCase):
+ pass
+else:
+ print
+ print '** WARNING: LIBFFI disabled, not testing'
+ print
+
if __name__ == '__main__':
unittest.main()
diff --git a/tests/testhelpermodule.c b/tests/testhelpermodule.c
index 48f6f6b..c811876 100644
--- a/tests/testhelpermodule.c
+++ b/tests/testhelpermodule.c
@@ -87,14 +87,6 @@ _wrap_test_g_object_new (PyObject * self)
return rv;
}
-static PyMethodDef testhelper_methods[] = {
- { "get_test_thread", (PyCFunction)_wrap_get_test_thread, METH_NOARGS },
- { "get_unknown", (PyCFunction)_wrap_get_unknown, METH_NOARGS },
- { "create_test_type", (PyCFunction)_wrap_create_test_type, METH_NOARGS },
- { "test_g_object_new", (PyCFunction)_wrap_test_g_object_new, METH_NOARGS },
- { NULL, NULL }
-};
-
/* TestUnknown */
static PyObject *
_wrap_test_interface_iface_method(PyGObject *self, PyObject *args, PyObject *kwargs)
@@ -319,6 +311,154 @@ static const GInterfaceInfo __TestInterface__iinfo = {
NULL
};
+#include <string.h>
+#include <glib-object.h>
+
+static void
+test1_callback (GObject *object, char *data)
+{
+ g_return_if_fail (G_IS_OBJECT (object));
+ g_return_if_fail (!strcmp (data, "user-data"));
+}
+
+static void
+test1_callback_swapped (char *data, GObject *object)
+{
+ g_return_if_fail (G_IS_OBJECT (object));
+ g_return_if_fail (!strcmp (data, "user-data"));
+}
+
+static void
+test2_callback (GObject *object, char *string)
+{
+ g_return_if_fail (G_IS_OBJECT (object));
+ g_return_if_fail (!strcmp (string, "string"));
+}
+
+static int
+test3_callback (GObject *object, double d)
+{
+ g_return_val_if_fail (G_IS_OBJECT (object), -1);
+ g_return_val_if_fail (d == 42.0, -1);
+
+ return 20;
+}
+
+static void
+test4_callback (GObject *object,
+ gboolean b, long l, float f, double d, guint uint, gulong ulong,
+ gpointer user_data)
+{
+ g_return_if_fail (b == TRUE);
+ g_return_if_fail (l == 10L);
+ g_return_if_fail (f <= 3.14001 && f >= 3.13999);
+ g_return_if_fail (d == 1.78);
+ g_return_if_fail (uint == 20);
+ g_return_if_fail (ulong == 30L);
+}
+
+static float
+test_float_callback (GObject *object, float f)
+{
+ g_return_val_if_fail (G_IS_OBJECT (object), -1);
+ g_return_val_if_fail (f <= 1.234001 && f >= 1.123999, -1);
+
+ return f;
+}
+
+static double
+test_double_callback (GObject *object, double d)
+{
+ g_return_val_if_fail (G_IS_OBJECT (object), -1);
+ g_return_val_if_fail (d <= 1.234001 && d >= 1.123999, -1);
+
+ return d;
+}
+
+static char *
+test_string_callback (GObject *object, char *s)
+{
+ g_return_val_if_fail (G_IS_OBJECT (object), NULL);
+ g_return_val_if_fail (!strcmp(s, "str"), NULL);
+
+ return g_strdup (s);
+}
+
+static GObject *
+test_object_callback (GObject *object, GObject *o)
+{
+ g_return_val_if_fail (G_IS_OBJECT (object), NULL);
+
+ return o;
+}
+
+void
+connectcallbacks (GObject *object)
+{
+
+ gchar *data = "user-data";
+
+ g_signal_connect (G_OBJECT (object),
+ "test1",
+ G_CALLBACK (test1_callback),
+ data);
+ g_signal_connect_swapped (G_OBJECT (object),
+ "test1",
+ G_CALLBACK (test1_callback_swapped),
+ data);
+ g_signal_connect (G_OBJECT (object),
+ "test2",
+ G_CALLBACK (test2_callback),
+ NULL);
+ g_signal_connect (G_OBJECT (object),
+ "test3",
+ G_CALLBACK (test3_callback),
+ NULL);
+ g_signal_connect (G_OBJECT (object),
+ "test4",
+ G_CALLBACK (test4_callback),
+ NULL);
+ g_signal_connect (G_OBJECT (object),
+ "test_float",
+ G_CALLBACK (test_float_callback),
+ NULL);
+ g_signal_connect (G_OBJECT (object),
+ "test_double",
+ G_CALLBACK (test_double_callback),
+ NULL);
+ g_signal_connect (G_OBJECT (object),
+ "test_string",
+ G_CALLBACK (test_string_callback),
+ NULL);
+ g_signal_connect (G_OBJECT (object),
+ "test_object",
+ G_CALLBACK (test_object_callback),
+ NULL);
+}
+
+static PyObject *
+_wrap_connectcallbacks(PyObject * self, PyObject *args)
+{
+ PyGObject *obj;
+
+ if (!PyArg_ParseTuple(args, "O", &obj))
+ return NULL;
+
+ connectcallbacks (G_OBJECT (obj->obj));
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyMethodDef testhelper_functions[] = {
+ { "get_test_thread", (PyCFunction)_wrap_get_test_thread, METH_NOARGS },
+ { "get_unknown", (PyCFunction)_wrap_get_unknown, METH_NOARGS },
+ { "create_test_type", (PyCFunction)_wrap_create_test_type, METH_NOARGS },
+ { "test_g_object_new", (PyCFunction)_wrap_test_g_object_new, METH_NOARGS },
+ { "connectcallbacks", (PyCFunction)_wrap_connectcallbacks, METH_VARARGS },
+ { NULL, NULL }
+};
+
void
inittesthelper ()
{
@@ -327,7 +467,7 @@ inittesthelper ()
init_pygobject();
g_thread_init(NULL);
- m = Py_InitModule ("testhelper", testhelper_methods);
+ m = Py_InitModule ("testhelper", testhelper_functions);
d = PyModule_GetDict(m);