[pygobject] Add capabilities to import wrappers from pygi



commit 000f7c36e667c6e078e3370769ea868e56a1b4ee
Author: Simon van der Linden <svdlinden src gnome org>
Date:   Sat Nov 7 16:43:35 2009 +0100

    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.

 configure.ac            |    8 +++++
 gobject/pygboxed.c      |   10 +++++++
 gobject/pygi-external.h |   66 +++++++++++++++++++++++++++++++++++++++++++++++
 gobject/pygobject.c     |   10 +++++++
 gobject/pygpointer.c    |   11 ++++++++
 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);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]