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