summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon van der Linden <svdlinden@src.gnome.org>2009-11-07 16:43:35 +0100
committerSimon van der Linden <svdlinden@src.gnome.org>2009-11-09 13:41:14 +0100
commit000f7c36e667c6e078e3370769ea868e56a1b4ee (patch)
tree87663b933462f0a376ed686b430141659f0f2bc1
parentbfd3100a580b8bea9db25b8bb7443fb8c3dbe1cc (diff)
downloadpygobject-000f7c36e667c6e078e3370769ea868e56a1b4ee.tar.gz
pygobject-000f7c36e667c6e078e3370769ea868e56a1b4ee.tar.xz
pygobject-000f7c36e667c6e078e3370769ea868e56a1b4ee.zip
Add capabilities to import wrappers from pygi
At instance creation for boxed and pointers, at lookup for objects, when the gtype has no wrapper yet, a wrapper may be imported from pygi. The feature is turned on at configure time by --enable-pygi. Because we couldn't create a circular build dependency, PyGI's import function and API definition had to be copied in this tree.
-rw-r--r--configure.ac8
-rw-r--r--gobject/pygboxed.c10
-rw-r--r--gobject/pygi-external.h66
-rw-r--r--gobject/pygobject.c10
-rw-r--r--gobject/pygpointer.c11
5 files changed, 105 insertions, 0 deletions
diff --git a/configure.ac b/configure.ac
index 0bf7610..dc8dea6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -215,6 +215,14 @@ if test "$enable_introspection" != no; then
fi
fi
+AC_ARG_ENABLE(pygi,
+ AC_HELP_STRING([--enable-pygi], [Use PyGI to create wrappers for introspection-enabled types]),
+ enable_pygi=$enableval,
+ enable_pygi=no)
+if test "$enable_pygi" != no; then
+ AC_DEFINE(ENABLE_PYGI,1,Use PyGI to create wrappers for introspection-enabled types)
+fi
+
dnl add required cflags ...
if test "x$GCC" = "xyes"; then
JH_ADD_CFLAG([-Wall])
diff --git a/gobject/pygboxed.c b/gobject/pygboxed.c
index eb274a2..8a4c8a8 100644
--- a/gobject/pygboxed.c
+++ b/gobject/pygboxed.c
@@ -28,6 +28,8 @@
#include "pygobject-private.h"
#include "pygboxed.h"
+#include "pygi-external.h"
+
GQuark pygboxed_type_key;
GQuark pygboxed_marshal_key;
@@ -182,6 +184,14 @@ pyg_boxed_new(GType boxed_type, gpointer boxed, gboolean copy_boxed,
}
tp = g_type_get_qdata(boxed_type, pygboxed_type_key);
+
+ if (tp == NULL) {
+ tp = (PyTypeObject *)pygi_type_import_by_g_type(boxed_type);
+ if (tp == NULL) {
+ PyErr_Clear();
+ }
+ }
+
if (!tp)
tp = (PyTypeObject *)&PyGBoxed_Type; /* fallback */
self = PyObject_NEW(PyGBoxed, tp);
diff --git a/gobject/pygi-external.h b/gobject/pygi-external.h
new file mode 100644
index 0000000..e0d11c2
--- /dev/null
+++ b/gobject/pygi-external.h
@@ -0,0 +1,66 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * vim: tabstop=4 shiftwidth=4 expandtab
+ */
+
+#ifndef _PYGI_EXTERNAL_H_
+#define _PYGI_EXTERNAL_H_
+
+#include <Python.h>
+#include <glib.h>
+
+struct PyGI_API {
+ PyObject* (*type_import_by_g_type) (GType g_type);
+};
+
+static struct PyGI_API *PyGI_API = NULL;
+
+static int
+_pygi_import (void)
+{
+#if ENABLE_PYGI
+ PyObject *module;
+ PyObject *api;
+
+ if (PyGI_API != NULL) {
+ return 1;
+ }
+
+ module = PyImport_ImportModule("gi");
+ if (module == NULL) {
+ return -1;
+ }
+
+ api = PyObject_GetAttrString(module, "_API");
+ if (api == NULL) {
+ Py_DECREF(module);
+ return -1;
+ }
+ if (!PyCObject_Check(api)) {
+ Py_DECREF(module);
+ Py_DECREF(api);
+ PyErr_Format(PyExc_TypeError, "gi._API must be cobject, not %s",
+ api->ob_type->tp_name);
+ return -1;
+ }
+
+ PyGI_API = (struct PyGI_API *)PyCObject_AsVoidPtr(api);
+
+ Py_DECREF(module);
+
+ return 0;
+#else
+ PyErr_SetString(PyExc_ImportError, "PyGI support not enabled");
+ return -1;
+#endif /* ENABLE_PYGI */
+}
+
+static inline PyObject *
+pygi_type_import_by_g_type (GType g_type)
+{
+ if (_pygi_import() < 0) {
+ return NULL;
+ }
+ return PyGI_API->type_import_by_g_type(g_type);
+}
+
+#endif /* _PYGI_EXTERNAL_H_ */
diff --git a/gobject/pygobject.c b/gobject/pygobject.c
index b4274e1..222280b 100644
--- a/gobject/pygobject.c
+++ b/gobject/pygobject.c
@@ -29,6 +29,8 @@
#include "pyginterface.h"
#include "pygparamspec.h"
+#include "pygi-external.h"
+
static void pygobject_dealloc(PyGObject *self);
static int pygobject_traverse(PyGObject *self, visitproc visit, void *arg);
@@ -871,6 +873,14 @@ pygobject_lookup_class(GType gtype)
py_type = g_type_get_qdata(gtype, pygobject_class_key);
if (py_type == NULL) {
py_type = g_type_get_qdata(gtype, pyginterface_type_key);
+
+ if (py_type == NULL) {
+ py_type = (PyTypeObject *)pygi_type_import_by_g_type(gtype);
+ if (py_type == NULL) {
+ PyErr_Clear();
+ }
+ }
+
if (py_type == NULL) {
py_type = pygobject_new_with_interfaces(gtype);
g_type_set_qdata(gtype, pyginterface_type_key, py_type);
diff --git a/gobject/pygpointer.c b/gobject/pygpointer.c
index ee0a8da..449b80c 100644
--- a/gobject/pygpointer.c
+++ b/gobject/pygpointer.c
@@ -28,6 +28,9 @@
#include "pygobject-private.h"
#include "pygpointer.h"
+#include "pygi-external.h"
+
+
GQuark pygpointer_class_key;
PYGLIB_DEFINE_TYPE("gobject.GPointer", PyGPointer_Type, PyGPointer);
@@ -155,6 +158,14 @@ pyg_pointer_new(GType pointer_type, gpointer pointer)
}
tp = g_type_get_qdata(pointer_type, pygpointer_class_key);
+
+ if (tp == NULL) {
+ tp = (PyTypeObject *)pygi_type_import_by_g_type(pointer_type);
+ if (tp == NULL) {
+ PyErr_Clear();
+ }
+ }
+
if (!tp)
tp = (PyTypeObject *)&PyGPointer_Type; /* fallback */
self = PyObject_NEW(PyGPointer, tp);