[pygobject] Build the cairo shim as a python module so the _gi module stops linking to it



commit 89827314fd183eac07443c8e9d275ca9d4ce59df
Author: Tomeu Vizoso <tomeu vizoso collabora co uk>
Date:   Tue Jun 29 10:27:39 2010 +0200

    Build the cairo shim as a python module so the _gi module stops linking to it
    
    https://bugzilla.gnome.org/show_bug.cgi?id=623021

 configure.ac            |    2 +
 gi/Makefile.am          |   38 +++++++++-----
 gi/gimodule.c           |    8 +---
 gi/pygi-argument.c      |   10 +---
 gi/pygi-foreign-cairo.c |   56 ++++++++++++++++-----
 gi/pygi-foreign-cairo.h |   55 ---------------------
 gi/pygi-foreign.c       |  125 ++++++++++++++++++++++++++++-------------------
 gi/pygi-foreign.h       |   31 +++++------
 gi/pygi.h               |   40 +++++++++++++--
 9 files changed, 196 insertions(+), 169 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index e9c5440..1458681 100644
--- a/configure.ac
+++ b/configure.ac
@@ -213,6 +213,8 @@ if test "$enable_introspection" != no; then
     PKG_CHECK_MODULES(GI,
         glib-2.0 >= glib_required_version
         gobject-introspection-1.0 >= introspection_required_version
+    )
+    PKG_CHECK_MODULES(PYCAIRO,
         pycairo >= pycairo_required_version
     )
 fi
diff --git a/gi/Makefile.am b/gi/Makefile.am
index f0c9ea2..ef4b8ff 100644
--- a/gi/Makefile.am
+++ b/gi/Makefile.am
@@ -9,11 +9,6 @@ SUBDIRS = \
 
 INCLUDES = -I$(top_srcdir)/gobject
 
-AM_CFLAGS = \
-	$(PYTHON_INCLUDES) \
-	$(GI_CFLAGS) \
-	$(PYCAIRO_CFLAGS)
-
 pygidir = $(pkgpyexecdir)/gi
 pygi_PYTHON = \
 	types.py \
@@ -21,13 +16,15 @@ pygi_PYTHON = \
 	importer.py \
 	__init__.py
 
+_gi_la_CFLAGS = \
+	$(PYTHON_INCLUDES) \
+	$(GI_CFLAGS)
 _gi_la_LDFLAGS = \
 	-module \
 	-avoid-version \
 	-export-symbols-regex init_gi
 _gi_la_LIBADD = \
-	$(GI_LIBS) \
-	$(PYCAIRO_LIBS)
+	$(GI_LIBS)
 _gi_la_SOURCES = \
 	pygi-repository.c \
 	pygi-repository.h \
@@ -37,8 +34,6 @@ _gi_la_SOURCES = \
 	pygi-invoke.h \
 	pygi-foreign.c \
 	pygi-foreign.h \
-	pygi-foreign-cairo.c \
-	pygi-foreign-cairo.h \
 	pygi-struct.c \
 	pygi-struct.h \
 	pygi-argument.c \
@@ -56,16 +51,33 @@ _gi_la_SOURCES = \
 	pygobject-external.h \
 	gimodule.c
 
-pygi_LTLIBRARIES = _gi.la
+_gi_cairo_la_CFLAGS = \
+	$(PYTHON_INCLUDES) \
+	$(GI_CFLAGS) \
+	$(PYCAIRO_CFLAGS)
+_gi_cairo_la_LDFLAGS = \
+	-module \
+	-avoid-version \
+	-export-symbols-regex init_gi_cairo
+_gi_cairo_la_LIBADD = \
+	$(GI_LIBS) \
+	$(PYCAIRO_LIBS)
+_gi_cairo_la_SOURCES = \
+	pygi-foreign-cairo.c \
+	pygi-foreign-cairo.h
+
+pygi_LTLIBRARIES = _gi.la _gi_cairo.la
 
 # This is to ensure we have a symlink to the .so in the
 # build directory, which the Python interpreter can load
 # directly without having to know how to parse .la files.
 _gi.so: _gi.la
 	rm -f $@ && $(LN_S) .libs/$@ $@
+_gi_cairo.so: _gi_cairo.la
+	rm -f $@ && $(LN_S) .libs/$@ $@
 
-all-local: _gi.so
-check-local: _gi.so
+all-local: _gi.so _gi_cairo.so
+check-local: _gi.so _gi_cairo.so
 clean-local:
-	rm -f _gi.so
+	rm -f _gi.so _gi_cairo.so
 
diff --git a/gi/gimodule.c b/gi/gimodule.c
index 1a81abc..df0db7a 100644
--- a/gi/gimodule.c
+++ b/gi/gimodule.c
@@ -26,9 +26,6 @@
 
 #include <pygobject.h>
 
-# include <pycairo.h>
-Pycairo_CAPI_t *Pycairo_CAPI;
-
 static PyObject *
 _wrap_pyg_enum_add (PyObject *self,
                     PyObject *args,
@@ -244,6 +241,7 @@ static PyMethodDef _pygi_functions[] = {
 
 static struct PyGI_API CAPI = {
   pygi_type_import_by_g_type_real,
+  pygi_register_foreign_struct_real,
 };
 
 PyMODINIT_FUNC
@@ -265,10 +263,6 @@ init_gi (void)
         return;
     }
 
-    Pycairo_IMPORT;
-    if (Pycairo_CAPI == NULL)
-        return;
-
     _pygi_repository_register_types (m);
     _pygi_info_register_types (m);
     _pygi_struct_register_types (m);
diff --git a/gi/pygi-argument.c b/gi/pygi-argument.c
index 7437175..c6df559 100644
--- a/gi/pygi-argument.c
+++ b/gi/pygi-argument.c
@@ -962,15 +962,9 @@ array_item_error:
                             arg.v_pointer = g_boxed_copy (type, arg.v_pointer);
                         }
                     } else if ( (type == G_TYPE_NONE) && (g_struct_info_is_foreign (info))) {
-                        gint retval;
-
-                        retval = pygi_struct_foreign_convert_to_g_argument (
+                        PyObject *result;
+                        result = pygi_struct_foreign_convert_to_g_argument (
                                      object, type_info, transfer, &arg);
-
-                        if (!retval) {
-                            PyErr_SetString (PyExc_RuntimeError, "PyObject conversion to foreign struct failed");
-                            break;
-                        }
                     } else if (g_type_is_a (type, G_TYPE_POINTER) || type == G_TYPE_NONE) {
                         g_warn_if_fail (!g_type_info_is_pointer (type_info) || transfer == GI_TRANSFER_NOTHING);
                         arg.v_pointer = pyg_pointer_get (object, void);
diff --git a/gi/pygi-foreign-cairo.c b/gi/pygi-foreign-cairo.c
index 7ec71c1..08d50ad 100644
--- a/gi/pygi-foreign-cairo.c
+++ b/gi/pygi-foreign-cairo.c
@@ -23,12 +23,11 @@
 
 #include <cairo.h>
 #include <pycairo.h>
-extern Pycairo_CAPI_t *Pycairo_CAPI;
+Pycairo_CAPI_t *Pycairo_CAPI;
 
 #include "pygi-foreign.h"
-#include "pygi-foreign-cairo.h"
 
-gboolean
+PyObject *
 cairo_context_to_arg (PyObject       *value,
                       GITypeInfo     *type_info,
                       GITransfer      transfer,
@@ -39,11 +38,12 @@ cairo_context_to_arg (PyObject       *value,
     g_assert (transfer == GI_TRANSFER_NOTHING);
 
     cr = PycairoContext_GET (value);
-    if (!cr)
-        return FALSE;
+    if (!cr) {
+        return NULL;
+    }
 
     arg->v_pointer = cr;
-    return TRUE;
+    Py_RETURN_NONE;
 }
 
 PyObject *
@@ -56,16 +56,16 @@ cairo_context_from_arg (GITypeInfo *type_info, GArgument  *arg)
     return PycairoContext_FromContext (context, &PycairoContext_Type, NULL);
 }
 
-gboolean
+PyObject *
 cairo_context_release_arg (GITransfer  transfer, GITypeInfo *type_info,
                            GArgument  *arg)
 {
     cairo_destroy ( (cairo_t*) arg->v_pointer);
-    return TRUE;
+    Py_RETURN_NONE;
 }
 
 
-gboolean
+PyObject *
 cairo_surface_to_arg (PyObject       *value,
                       GITypeInfo     *type_info,
                       GITransfer      transfer,
@@ -76,11 +76,13 @@ cairo_surface_to_arg (PyObject       *value,
     g_assert (transfer == GI_TRANSFER_NOTHING);
 
     surface = ( (PycairoSurface*) value)->surface;
-    if (!surface)
-        return FALSE;
+    if (!surface) {
+        PyErr_SetString (PyExc_ValueError, "Surface instance wrapping a NULL surface");
+        return NULL;
+    }
 
     arg->v_pointer = surface;
-    return TRUE;
+    Py_RETURN_NONE;
 }
 
 PyObject *
@@ -93,11 +95,37 @@ cairo_surface_from_arg (GITypeInfo *type_info, GArgument  *arg)
     return PycairoSurface_FromSurface (surface, NULL);
 }
 
-gboolean
+PyObject *
 cairo_surface_release_arg (GITransfer  transfer, GITypeInfo *type_info,
                            GArgument  *arg)
 {
     cairo_surface_destroy ( (cairo_surface_t*) arg->v_pointer);
-    return TRUE;
+    Py_RETURN_NONE;
 }
 
+PyMODINIT_FUNC
+init_gi_cairo (void)
+{
+    PyObject *m;
+
+    m = Py_InitModule ("_gi_cairo", NULL);
+    if (m == NULL) {
+        return;
+    }
+
+    Pycairo_IMPORT;
+    if (Pycairo_CAPI == NULL)
+        return;
+
+    pygi_register_foreign_struct ("cairo",
+                                  "Context",
+                                  cairo_context_to_arg,
+                                  cairo_context_from_arg,
+                                  cairo_context_release_arg);
+
+    pygi_register_foreign_struct ("cairo",
+                                  "Surface",
+                                  cairo_surface_to_arg,
+                                  cairo_surface_from_arg,
+                                  cairo_surface_release_arg);
+}
diff --git a/gi/pygi-foreign.c b/gi/pygi-foreign.c
index d2613df..13a0f77 100644
--- a/gi/pygi-foreign.c
+++ b/gi/pygi-foreign.c
@@ -27,99 +27,122 @@
 #include <config.h>
 #include <girepository.h>
 
-#include "pygi-foreign-cairo.h"
-
-static struct {
-    char *namespace;
-    char *name;
+typedef struct {
+    const char *namespace;
+    const char *name;
     PyGIArgOverrideToGArgumentFunc to_func;
     PyGIArgOverrideFromGArgumentFunc from_func;
     PyGIArgOverrideReleaseGArgumentFunc release_func;
-} foreign_structs[] = {
-    {   "cairo", "Context", cairo_context_to_arg, cairo_context_from_arg,
-        cairo_context_release_arg
-    },
-    {   "cairo", "Surface", cairo_surface_to_arg, cairo_surface_from_arg,
-        cairo_surface_release_arg
-    },
-    { NULL }
-};
-
-static gint
+} PyGIForeignStruct;
+
+static GPtrArray *foreign_structs = NULL;
+
+static PyGIForeignStruct *
 pygi_struct_foreign_lookup (GITypeInfo *type_info)
 {
+    gint i;
+    PyObject *module;
+    gchar *module_name;
     GIBaseInfo *base_info;
+    const gchar *namespace;
+    const gchar *name;
 
     base_info = g_type_info_get_interface (type_info);
-    if (base_info) {
-        gint i;
-        const gchar *namespace = g_base_info_get_namespace (base_info);
-        const gchar *name = g_base_info_get_name (base_info);
+    if (base_info == NULL) {
+        PyErr_Format (PyExc_ValueError, "Couldn't resolve the type of this foreign struct");
+        return NULL;
+    }
 
-        for (i = 0; foreign_structs[i].namespace; ++i) {
+    namespace = g_base_info_get_namespace (base_info);
+    name = g_base_info_get_name (base_info);
 
-            if ( (strcmp (namespace, foreign_structs[i].namespace) == 0) &&
-                    (strcmp (name, foreign_structs[i].name) == 0)) {
+    module_name = g_strconcat ("gi._gi_", g_base_info_get_namespace (base_info), NULL);
+    module = PyImport_ImportModule (module_name);
+    g_free (module_name);
+
+    if (foreign_structs != NULL) {
+        for (i = 0; i < foreign_structs->len; i++) {
+            PyGIForeignStruct *foreign_struct = \
+                    g_ptr_array_index (foreign_structs, i);
+
+            if ( (strcmp (namespace, foreign_struct->namespace) == 0) &&
+                    (strcmp (name, foreign_struct->name) == 0)) {
                 g_base_info_unref (base_info);
-                return i;
+                return foreign_struct;
             }
         }
+    }
 
-        PyErr_Format (PyExc_TypeError, "Couldn't find type %s.%s", namespace,
-                      name);
+    g_base_info_unref (base_info);
 
-        g_base_info_unref (base_info);
-    }
-    return -1;
+    PyErr_Format (PyExc_TypeError, "Couldn't find conversion for foreign struct '%s.%s'", namespace, name);
+    return NULL;
 }
 
-gboolean
+PyObject *
 pygi_struct_foreign_convert_to_g_argument (PyObject      *value,
                                            GITypeInfo     *type_info,
                                            GITransfer      transfer,
                                            GArgument      *arg)
 {
-    gint struct_index;
+    PyGIForeignStruct *foreign_struct = pygi_struct_foreign_lookup (type_info);
 
-    struct_index = pygi_struct_foreign_lookup (type_info);
-    if (struct_index < 0)
-        return FALSE;
+    if (foreign_struct == NULL)
+        return NULL;
 
-    if (!foreign_structs[struct_index].to_func (value, type_info, transfer, arg))
-        return FALSE;
+    if (!foreign_struct->to_func (value, type_info, transfer, arg))
+        return NULL;
 
-    return TRUE;
+    Py_RETURN_NONE;
 }
 
 PyObject *
 pygi_struct_foreign_convert_from_g_argument (GITypeInfo *type_info,
                                              GArgument  *arg)
 {
-    gint struct_index;
+    PyGIForeignStruct *foreign_struct = pygi_struct_foreign_lookup (type_info);
 
-    struct_index = pygi_struct_foreign_lookup (type_info);
-    if (struct_index < 0)
+    if (foreign_struct == NULL)
         return NULL;
 
-    return foreign_structs[struct_index].from_func (type_info, arg);
+    return foreign_struct->from_func (type_info, arg);
 }
 
-gboolean
+PyObject *
 pygi_struct_foreign_release_g_argument (GITransfer  transfer,
                                         GITypeInfo *type_info,
                                         GArgument  *arg)
 {
-    gint struct_index;
+    PyGIForeignStruct *foreign_struct = pygi_struct_foreign_lookup (type_info);
+
+    if (foreign_struct == NULL)
+        return NULL;
 
-    struct_index = pygi_struct_foreign_lookup (type_info);
-    if (struct_index < 0)
-        return FALSE;
+    if (!foreign_struct->release_func)
+        Py_RETURN_NONE;
 
-    if (!foreign_structs[struct_index].release_func)
-        return TRUE;
+    if (!foreign_struct->release_func (transfer, type_info, arg))
+        return NULL;
+
+    Py_RETURN_NONE;
+}
+
+void
+pygi_register_foreign_struct_real (const char* namespace_,
+                                   const char* name,
+                                   PyGIArgOverrideToGArgumentFunc to_func,
+                                   PyGIArgOverrideFromGArgumentFunc from_func,
+                                   PyGIArgOverrideReleaseGArgumentFunc release_func)
+{
+    PyGIForeignStruct *new_struct = g_slice_new0 (PyGIForeignStruct);
+    new_struct->namespace = namespace_;
+    new_struct->name = name;
+    new_struct->to_func = to_func;
+    new_struct->from_func = from_func;
+    new_struct->release_func = release_func;
 
-    if (!foreign_structs[struct_index].release_func (transfer, type_info, arg))
-        return FALSE;
+    if (foreign_structs == NULL)
+        foreign_structs = g_ptr_array_new ();
 
-    return TRUE;
+    g_ptr_array_add (foreign_structs, new_struct);
 }
diff --git a/gi/pygi-foreign.h b/gi/pygi-foreign.h
index 7962b49..9a35bd8 100644
--- a/gi/pygi-foreign.h
+++ b/gi/pygi-foreign.h
@@ -28,25 +28,22 @@
 #include <Python.h>
 #include <girepository.h>
 
-typedef gboolean (*PyGIArgOverrideToGArgumentFunc) (PyObject       *value,
-                                                    GITypeInfo     *type_info,
-                                                    GITransfer      transfer,
-                                                    GArgument      *arg);
+#include "pygi.h"
 
-typedef PyObject * (*PyGIArgOverrideFromGArgumentFunc) (GITypeInfo *type_info,
-                                                        GArgument  *arg);
-typedef gboolean (*PyGIArgOverrideReleaseGArgumentFunc) (GITransfer  transfer,
-                                                         GITypeInfo *type_info,
-                                                         GArgument  *arg);
-
-gboolean pygi_struct_foreign_convert_to_g_argument (PyObject           *value,
-                                                    GITypeInfo         *type_info,
-                                                    GITransfer          transfer,
-                                                    GArgument          *arg);
+PyObject *pygi_struct_foreign_convert_to_g_argument (PyObject           *value,
+                                                     GITypeInfo         *type_info,
+                                                     GITransfer          transfer,
+                                                     GArgument          *arg);
 PyObject *pygi_struct_foreign_convert_from_g_argument (GITypeInfo *type_info,
                                                        GArgument  *arg);
-gboolean pygi_struct_foreign_release_g_argument (GITransfer          transfer,
-                                                 GITypeInfo         *type_info,
-                                                 GArgument          *arg);
+PyObject *pygi_struct_foreign_release_g_argument (GITransfer          transfer,
+                                                  GITypeInfo         *type_info,
+                                                  GArgument          *arg);
+
+void pygi_register_foreign_struct_real (const char* namespace_,
+                                        const char* name,
+                                        PyGIArgOverrideToGArgumentFunc to_func,
+                                        PyGIArgOverrideFromGArgumentFunc from_func,
+                                        PyGIArgOverrideReleaseGArgumentFunc release_func);
 
 #endif /* __PYGI_FOREIGN_H__ */
diff --git a/gi/pygi.h b/gi/pygi.h
index 667fa70..0a8cbf5 100644
--- a/gi/pygi.h
+++ b/gi/pygi.h
@@ -51,9 +51,23 @@ typedef struct {
     gsize size;
 } PyGIBoxed;
 
+typedef PyObject * (*PyGIArgOverrideToGArgumentFunc) (PyObject       *value,
+                                                      GITypeInfo     *type_info,
+                                                      GITransfer      transfer,
+                                                      GArgument      *arg);
+typedef PyObject * (*PyGIArgOverrideFromGArgumentFunc) (GITypeInfo *type_info,
+                                                        GArgument  *arg);
+typedef PyObject * (*PyGIArgOverrideReleaseGArgumentFunc) (GITransfer  transfer,
+                                                           GITypeInfo *type_info,
+                                                           GArgument  *arg);
 
 struct PyGI_API {
     PyObject* (*type_import_by_g_type) (GType g_type);
+    void (*register_foreign_struct) (const char* namespace_,
+                                     const char* name,
+                                     PyGIArgOverrideToGArgumentFunc to_func,
+                                     PyGIArgOverrideFromGArgumentFunc from_func,
+                                     PyGIArgOverrideReleaseGArgumentFunc release_func);
 };
 
 static struct PyGI_API *PyGI_API = NULL;
@@ -76,10 +90,28 @@ _pygi_import (void)
 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);
+    if (_pygi_import() < 0) {
+        return NULL;
+    }
+    return PyGI_API->type_import_by_g_type(g_type);
+}
+
+static inline PyObject *
+pygi_register_foreign_struct (const char* namespace_,
+                              const char* name,
+                              PyGIArgOverrideToGArgumentFunc to_func,
+                              PyGIArgOverrideFromGArgumentFunc from_func,
+                              PyGIArgOverrideReleaseGArgumentFunc release_func)
+{
+    if (_pygi_import() < 0) {
+        return NULL;
+    }
+    PyGI_API->register_foreign_struct(namespace_,
+                                      name,
+                                      to_func,
+                                      from_func,
+                                      release_func);
+    Py_RETURN_NONE;
 }
 
 #else /* ENABLE_INTROSPECTION */



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