[pygi] Add support for foreign structs
- From: Tomeu Vizoso <tomeuv src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pygi] Add support for foreign structs
- Date: Sat, 17 Apr 2010 14:59:24 +0000 (UTC)
commit a34cb9f0038a6c89e5e6c5f7761d48a5a833044f
Author: Tomeu Vizoso <tomeu sugarlabs org>
Date: Sat Apr 17 10:54:45 2010 -0400
Add support for foreign structs
https://bugzilla.gnome.org/show_bug.cgi?id=603712
configure.ac | 6 ++
gi/Makefile.am | 10 +++-
gi/gimodule.c | 7 +++
gi/pygi-argument.c | 27 +++++++++-
gi/pygi-foreign-cairo.c | 103 ++++++++++++++++++++++++++++++++++++++
gi/pygi-foreign-cairo.h | 55 ++++++++++++++++++++
gi/pygi-foreign.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++
gi/pygi-foreign.h | 52 +++++++++++++++++++
gi/pygi-private.h | 1 +
tests/test_everything.py | 48 ++++++++++++++++++
10 files changed, 428 insertions(+), 4 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 33f30e9..3a596c3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -47,6 +47,12 @@ INTROSPECTION_COMPILER=`$PKG_CONFIG --variable=g_ir_compiler gobject-introspecti
AC_SUBST(INTROSPECTION_SCANNER)
AC_SUBST(INTROSPECTION_COMPILER)
+m4_define(pycairo_required_version, 1.0.2)
+PKG_CHECK_MODULES(PYCAIRO, [pycairo >= pycairo_required_version],
+ have_pycairo=true, have_pycairo=false)
+AC_SUBST(PYCAIRO_CFLAGS)
+AC_SUBST(PYCAIRO_LIBS)
+
AC_OUTPUT(
Makefile
gi/Makefile
diff --git a/gi/Makefile.am b/gi/Makefile.am
index 63f90e3..0299d01 100644
--- a/gi/Makefile.am
+++ b/gi/Makefile.am
@@ -8,7 +8,8 @@ SUBDIRS = \
overrides
AM_CFLAGS = \
$(PYTHON_INCLUDES) \
- $(GNOME_CFLAGS)
+ $(GNOME_CFLAGS) \
+ $(PYCAIRO_CFLAGS)
pygidir = $(pkgpyexecdir)/gi
pygi_PYTHON = \
@@ -22,12 +23,17 @@ _gi_la_LDFLAGS = \
-avoid-version \
-export-symbols-regex init_gi
_gi_la_LIBADD = \
- $(GNOME_LIBS)
+ $(GNOME_LIBS) \
+ $(PYCAIRO_LIBS)
_gi_la_SOURCES = \
pygi-repository.c \
pygi-repository.h \
pygi-info.c \
pygi-info.h \
+ pygi-foreign.c \
+ pygi-foreign.h \
+ pygi-foreign-cairo.c \
+ pygi-foreign-cairo.h \
pygi-struct.c \
pygi-struct.h \
pygi-argument.c \
diff --git a/gi/gimodule.c b/gi/gimodule.c
index 8811539..8dd8ac5 100644
--- a/gi/gimodule.c
+++ b/gi/gimodule.c
@@ -25,6 +25,9 @@
#include <pygobject.h>
+# include <pycairo.h>
+Pycairo_CAPI_t *Pycairo_CAPI;
+
static PyObject *
_wrap_pyg_enum_add (PyObject *self,
PyObject *args,
@@ -163,6 +166,10 @@ 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 edbb31f..335074e 100644
--- a/gi/pygi-argument.c
+++ b/gi/pygi-argument.c
@@ -121,9 +121,16 @@ _pygi_g_registered_type_info_check_object (GIRegisteredTypeInfo *info,
GType g_type;
PyObject *py_type;
gchar *type_name_expected = NULL;
+ GIInfoType interface_type;
- g_type = g_registered_type_info_get_g_type(info);
+ interface_type = g_base_info_get_type(info);
+ if ((interface_type == GI_INFO_TYPE_STRUCT) &&
+ (g_struct_info_is_foreign((GIStructInfo*)info))) {
+ /* TODO: Could we check is the correct foreign type? */
+ return 1;
+ }
+ g_type = g_registered_type_info_get_g_type(info);
if (g_type != G_TYPE_NONE) {
py_type = _pygi_type_get_from_g_type(g_type);
} else {
@@ -131,7 +138,7 @@ _pygi_g_registered_type_info_check_object (GIRegisteredTypeInfo *info,
}
if (py_type == NULL) {
- return FALSE;
+ return 0;
}
g_assert(PyType_Check(py_type));
@@ -932,6 +939,16 @@ array_item_error:
if (transfer == GI_TRANSFER_EVERYTHING) {
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(
+ 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);
@@ -1433,6 +1450,8 @@ _pygi_argument_to_object (GArgument *arg,
}
Py_XDECREF(py_type);
+ } else if ((type == G_TYPE_NONE) && (g_struct_info_is_foreign (info))) {
+ object = pygi_struct_foreign_convert_from_g_argument(type_info, arg->v_pointer);
} else if (type == G_TYPE_NONE) {
PyObject *py_type;
@@ -1721,6 +1740,10 @@ _pygi_argument_release (GArgument *arg,
if (direction == GI_DIRECTION_IN && transfer == GI_TRANSFER_NOTHING) {
g_closure_unref(arg->v_pointer);
}
+ } else if (g_struct_info_is_foreign((GIStructInfo*)info)) {
+ if (direction == GI_DIRECTION_OUT && transfer == GI_TRANSFER_EVERYTHING) {
+ pygi_struct_foreign_release_g_argument(transfer, type_info, arg);
+ }
} else if (g_type_is_a(type, G_TYPE_BOXED)) {
} 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);
diff --git a/gi/pygi-foreign-cairo.c b/gi/pygi-foreign-cairo.c
new file mode 100644
index 0000000..a051d33
--- /dev/null
+++ b/gi/pygi-foreign-cairo.c
@@ -0,0 +1,103 @@
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright (c) 2010 Collabora Ltd. <http://www.collabora.co.uk/>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <cairo.h>
+#include <pycairo.h>
+extern Pycairo_CAPI_t *Pycairo_CAPI;
+
+#include "pygi-foreign.h"
+#include "pygi-foreign-cairo.h"
+
+gboolean
+cairo_context_to_arg(PyObject *value,
+ GITypeInfo *type_info,
+ GITransfer transfer,
+ GArgument *arg)
+{
+ cairo_t *cr;
+
+ g_assert (transfer == GI_TRANSFER_NOTHING);
+
+ cr = PycairoContext_GET(value);
+ if (!cr)
+ return FALSE;
+
+ arg->v_pointer = cr;
+ return TRUE;
+}
+
+PyObject *
+cairo_context_from_arg(GITypeInfo *type_info, GArgument *arg)
+{
+ cairo_t *context = (cairo_t*) arg;
+
+ cairo_reference (context);
+
+ return PycairoContext_FromContext (context, &PycairoContext_Type, NULL);
+}
+
+gboolean
+cairo_context_release_arg(GITransfer transfer, GITypeInfo *type_info,
+ GArgument *arg)
+{
+ cairo_destroy((cairo_t*)arg->v_pointer);
+ return TRUE;
+}
+
+
+gboolean
+cairo_surface_to_arg(PyObject *value,
+ GITypeInfo *type_info,
+ GITransfer transfer,
+ GArgument *arg)
+{
+ cairo_surface_t *surface;
+
+ g_assert (transfer == GI_TRANSFER_NOTHING);
+
+ surface = ((PycairoSurface*)value)->surface;
+ if (!surface)
+ return FALSE;
+
+ arg->v_pointer = surface;
+ return TRUE;
+}
+
+PyObject *
+cairo_surface_from_arg(GITypeInfo *type_info, GArgument *arg)
+{
+ cairo_surface_t *surface = (cairo_surface_t*) arg;
+
+ cairo_surface_reference (surface);
+
+ return PycairoSurface_FromSurface (surface, NULL);
+}
+
+gboolean
+cairo_surface_release_arg(GITransfer transfer, GITypeInfo *type_info,
+ GArgument *arg)
+{
+ cairo_surface_destroy((cairo_surface_t*)arg->v_pointer);
+ return TRUE;
+}
+
diff --git a/gi/pygi-foreign-cairo.h b/gi/pygi-foreign-cairo.h
new file mode 100644
index 0000000..b8dbcaa
--- /dev/null
+++ b/gi/pygi-foreign-cairo.h
@@ -0,0 +1,55 @@
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright (c) 2010 Collabora Ltd. <http://www.collabora.co.uk/>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef __PYGI_FOREIGN_CAIRO_H__
+#define __PYGI_FOREIGN_CAIRO_H__
+
+#include "pygi-foreign.h"
+
+gboolean cairo_context_to_arg(PyObject *value,
+ GITypeInfo *type_info,
+ GITransfer transfer,
+ GArgument *arg);
+
+PyObject *cairo_context_from_arg(GITypeInfo *type_info,
+ GArgument *arg);
+
+gboolean cairo_context_release_arg(GITransfer transfer,
+ GITypeInfo *type_info,
+ GArgument *arg);
+
+
+gboolean cairo_surface_to_arg(PyObject *value,
+ GITypeInfo *type_info,
+ GITransfer transfer,
+ GArgument *arg);
+
+PyObject *cairo_surface_from_arg(GITypeInfo *type_info,
+ GArgument *arg);
+
+gboolean cairo_surface_release_arg(GITransfer transfer,
+ GITypeInfo *type_info,
+ GArgument *arg);
+
+#endif /* __PYGI_FOREIGN_CAIRO_H__ */
+
diff --git a/gi/pygi-foreign.c b/gi/pygi-foreign.c
new file mode 100644
index 0000000..cde56b0
--- /dev/null
+++ b/gi/pygi-foreign.c
@@ -0,0 +1,123 @@
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright (c) 2010 litl, LLC
+ * Copyright (c) 2010 Collabora Ltd. <http://www.collabora.co.uk/>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "pygi-foreign.h"
+
+#include <config.h>
+#include <girepository.h>
+
+#include "pygi-foreign-cairo.h"
+
+static struct {
+ char *namespace;
+ 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
+pygi_struct_foreign_lookup(GITypeInfo *type_info)
+{
+ GIBaseInfo *base_info;
+
+ 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);
+
+ for (i = 0; foreign_structs[i].namespace; ++i) {
+
+ if ((strcmp(namespace, foreign_structs[i].namespace) == 0) &&
+ (strcmp(name, foreign_structs[i].name) == 0)) {
+ g_base_info_unref(base_info);
+ return i;
+ }
+ }
+
+ PyErr_Format(PyExc_TypeError, "Couldn't find type %s.%s", namespace,
+ name);
+
+ g_base_info_unref(base_info);
+ }
+ return -1;
+}
+
+gboolean
+pygi_struct_foreign_convert_to_g_argument(PyObject *value,
+ GITypeInfo *type_info,
+ GITransfer transfer,
+ GArgument *arg)
+{
+ gint struct_index;
+
+ struct_index = pygi_struct_foreign_lookup (type_info);
+ if (struct_index < 0)
+ return FALSE;
+
+ if (!foreign_structs[struct_index].to_func(value, type_info, transfer, arg))
+ return FALSE;
+
+ return TRUE;
+}
+
+PyObject *
+pygi_struct_foreign_convert_from_g_argument(GITypeInfo *type_info,
+ GArgument *arg)
+{
+ gint struct_index;
+
+ struct_index = pygi_struct_foreign_lookup (type_info);
+ if (struct_index < 0)
+ return NULL;
+
+ return foreign_structs[struct_index].from_func(type_info, arg);
+}
+
+gboolean
+pygi_struct_foreign_release_g_argument(GITransfer transfer,
+ GITypeInfo *type_info,
+ GArgument *arg)
+{
+ gint struct_index;
+
+ struct_index = pygi_struct_foreign_lookup (type_info);
+ if (struct_index < 0)
+ return FALSE;
+
+ if (!foreign_structs[struct_index].release_func)
+ return TRUE;
+
+ if (!foreign_structs[struct_index].release_func(transfer, type_info, arg))
+ return FALSE;
+
+ return TRUE;
+}
diff --git a/gi/pygi-foreign.h b/gi/pygi-foreign.h
new file mode 100644
index 0000000..2f13b0f
--- /dev/null
+++ b/gi/pygi-foreign.h
@@ -0,0 +1,52 @@
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright (c) 2010 litl, LLC
+ * Copyright (c) 2010 Collabora Ltd. <http://www.collabora.co.uk/>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef __PYGI_FOREIGN_H__
+#define __PYGI_FOREIGN_H__
+
+#include <Python.h>
+#include <girepository.h>
+
+typedef gboolean (*PyGIArgOverrideToGArgumentFunc) (PyObject *value,
+ GITypeInfo *type_info,
+ GITransfer transfer,
+ GArgument *arg);
+
+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_from_g_argument(GITypeInfo *type_info,
+ GArgument *arg);
+gboolean pygi_struct_foreign_release_g_argument (GITransfer transfer,
+ GITypeInfo *type_info,
+ GArgument *arg);
+
+#endif /* __PYGI_FOREIGN_H__ */
diff --git a/gi/pygi-private.h b/gi/pygi-private.h
index 562c8ab..9f39d0d 100644
--- a/gi/pygi-private.h
+++ b/gi/pygi-private.h
@@ -24,6 +24,7 @@
#include "pygi-boxed.h"
#include "pygi-argument.h"
#include "pygi-type.h"
+#include "pygi-foreign.h"
G_BEGIN_DECLS
diff --git a/tests/test_everything.py b/tests/test_everything.py
new file mode 100644
index 0000000..60e8f9d
--- /dev/null
+++ b/tests/test_everything.py
@@ -0,0 +1,48 @@
+# -*- Mode: Python; py-indent-offset: 4 -*-
+# vim: tabstop=4 shiftwidth=4 expandtab
+
+import unittest
+
+import sys
+sys.path.insert(0, "../")
+
+import gobject
+import cairo
+
+from gi.repository import Everything
+
+class TestEverything(unittest.TestCase):
+
+ def test_cairo_context(self):
+ context = Everything.test_cairo_context_full_return()
+ self.assertTrue(isinstance(context, cairo.Context))
+
+ surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10)
+ context = cairo.Context(surface)
+ Everything.test_cairo_context_none_in(context)
+
+ def test_cairo_surface(self):
+ surface = Everything.test_cairo_surface_none_return()
+ self.assertTrue(isinstance(surface, cairo.ImageSurface))
+ self.assertTrue(isinstance(surface, cairo.Surface))
+ self.assertEquals(surface.get_format(), cairo.FORMAT_ARGB32)
+ self.assertEquals(surface.get_width(), 10)
+ self.assertEquals(surface.get_height(), 10)
+
+ surface = Everything.test_cairo_surface_full_return()
+ self.assertTrue(isinstance(surface, cairo.ImageSurface))
+ self.assertTrue(isinstance(surface, cairo.Surface))
+ self.assertEquals(surface.get_format(), cairo.FORMAT_ARGB32)
+ self.assertEquals(surface.get_width(), 10)
+ self.assertEquals(surface.get_height(), 10)
+
+ surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10)
+ Everything.test_cairo_surface_none_in(surface)
+
+ surface = Everything.test_cairo_surface_full_out()
+ self.assertTrue(isinstance(surface, cairo.ImageSurface))
+ self.assertTrue(isinstance(surface, cairo.Surface))
+ self.assertEquals(surface.get_format(), cairo.FORMAT_ARGB32)
+ self.assertEquals(surface.get_width(), 10)
+ self.assertEquals(surface.get_height(), 10)
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]