[pygobject] Add foreign struct support for GVariant
- From: Tomeu Vizoso <tomeuv src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pygobject] Add foreign struct support for GVariant
- Date: Thu, 15 Jul 2010 11:34:49 +0000 (UTC)
commit e65275bc57f345c111eb12a6b4476ff1ddc3bc24
Author: Tomeu Vizoso <tomeu vizoso collabora co uk>
Date: Thu Jul 15 13:31:33 2010 +0200
Add foreign struct support for GVariant
* gi/pygi-invoke.c: Wrap foreign structs returned by constructors
* gi/pygi-foreign.c: Register foreign support for GVariant
* gi/pygi-struct.c: properly release foreign structs
* gi/pygi-argument.c, gi/pygi-foreign-cairo.c, gi/pygi.h: Adapt to API changes
* tests/test_everything.py: Add basic tests for GVariant
https://bugzilla.gnome.org/show_bug.cgi?id=619501
gi/Makefile.am | 2 +
gi/pygi-argument.c | 2 +-
gi/pygi-foreign-cairo.c | 16 +++---
gi/pygi-foreign.c | 107 ++++++++++++++++++++++++++++-----------------
gi/pygi-foreign.h | 7 +--
gi/pygi-invoke.c | 18 ++++----
gi/pygi-struct.c | 10 ++++-
gi/pygi.h | 9 ++--
tests/test_everything.py | 8 +++
9 files changed, 110 insertions(+), 69 deletions(-)
---
diff --git a/gi/Makefile.am b/gi/Makefile.am
index c651c97..fc57edb 100644
--- a/gi/Makefile.am
+++ b/gi/Makefile.am
@@ -34,6 +34,8 @@ _gi_la_SOURCES = \
pygi-invoke.h \
pygi-foreign.c \
pygi-foreign.h \
+ pygi-foreign-gvariant.c \
+ pygi-foreign-gvariant.h \
pygi-struct.c \
pygi-struct.h \
pygi-argument.c \
diff --git a/gi/pygi-argument.c b/gi/pygi-argument.c
index 9ace5d2..1b2e0d2 100644
--- a/gi/pygi-argument.c
+++ b/gi/pygi-argument.c
@@ -1649,7 +1649,7 @@ _pygi_argument_release (GArgument *arg,
}
} 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);
+ pygi_struct_foreign_release (info, arg->v_pointer);
}
} else if (g_type_is_a (type, G_TYPE_BOXED)) {
} else if (g_type_is_a (type, G_TYPE_POINTER) || type == G_TYPE_NONE) {
diff --git a/gi/pygi-foreign-cairo.c b/gi/pygi-foreign-cairo.c
index 08d50ad..56c9321 100644
--- a/gi/pygi-foreign-cairo.c
+++ b/gi/pygi-foreign-cairo.c
@@ -57,10 +57,10 @@ cairo_context_from_arg (GITypeInfo *type_info, GArgument *arg)
}
PyObject *
-cairo_context_release_arg (GITransfer transfer, GITypeInfo *type_info,
- GArgument *arg)
+cairo_context_release (GIBaseInfo *base_info,
+ gpointer struct_)
{
- cairo_destroy ( (cairo_t*) arg->v_pointer);
+ cairo_destroy ( (cairo_t*) struct_);
Py_RETURN_NONE;
}
@@ -96,10 +96,10 @@ cairo_surface_from_arg (GITypeInfo *type_info, GArgument *arg)
}
PyObject *
-cairo_surface_release_arg (GITransfer transfer, GITypeInfo *type_info,
- GArgument *arg)
+cairo_surface_release (GIBaseInfo *base_info,
+ gpointer struct_)
{
- cairo_surface_destroy ( (cairo_surface_t*) arg->v_pointer);
+ cairo_surface_destroy ( (cairo_surface_t*) struct_);
Py_RETURN_NONE;
}
@@ -121,11 +121,11 @@ init_gi_cairo (void)
"Context",
cairo_context_to_arg,
cairo_context_from_arg,
- cairo_context_release_arg);
+ cairo_context_release);
pygi_register_foreign_struct ("cairo",
"Surface",
cairo_surface_to_arg,
cairo_surface_from_arg,
- cairo_surface_release_arg);
+ cairo_surface_release);
}
diff --git a/gi/pygi-foreign.c b/gi/pygi-foreign.c
index 13a0f77..c80c42d 100644
--- a/gi/pygi-foreign.c
+++ b/gi/pygi-foreign.c
@@ -23,6 +23,7 @@
*/
#include "pygi-foreign.h"
+#include "pygi-foreign-gvariant.h"
#include <config.h>
#include <girepository.h>
@@ -32,60 +33,85 @@ typedef struct {
const char *name;
PyGIArgOverrideToGArgumentFunc to_func;
PyGIArgOverrideFromGArgumentFunc from_func;
- PyGIArgOverrideReleaseGArgumentFunc release_func;
+ PyGIArgOverrideReleaseFunc release_func;
} PyGIForeignStruct;
static GPtrArray *foreign_structs = NULL;
+void
+init_foreign_structs ()
+{
+ foreign_structs = g_ptr_array_new ();
+
+ pygi_register_foreign_struct ("GLib",
+ "Variant",
+ g_variant_to_arg,
+ g_variant_from_arg,
+ g_variant_release_foreign);
+}
+
static PyGIForeignStruct *
-pygi_struct_foreign_lookup (GITypeInfo *type_info)
+do_lookup (const gchar *namespace, const gchar *name)
{
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 == NULL) {
- PyErr_Format (PyExc_ValueError, "Couldn't resolve the type of this foreign struct");
- return 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)) {
+ return foreign_struct;
+ }
+ }
+ return NULL;
+}
+
+static PyGIForeignStruct *
+pygi_struct_foreign_lookup (GIBaseInfo *base_info)
+{
+ PyGIForeignStruct *result;
+ const gchar *namespace = g_base_info_get_namespace (base_info);
+ const gchar *name = g_base_info_get_name (base_info);
+
+ if (foreign_structs == NULL) {
+ init_foreign_structs ();
}
- namespace = g_base_info_get_namespace (base_info);
- name = g_base_info_get_name (base_info);
+ result = do_lookup (namespace, name);
- module_name = g_strconcat ("gi._gi_", g_base_info_get_namespace (base_info), NULL);
- module = PyImport_ImportModule (module_name);
- g_free (module_name);
+ if (result == NULL) {
+ gchar *module_name = g_strconcat ("gi._gi_", namespace, NULL);
+ PyObject *module = PyImport_ImportModule (module_name);
- if (foreign_structs != NULL) {
- for (i = 0; i < foreign_structs->len; i++) {
- PyGIForeignStruct *foreign_struct = \
- g_ptr_array_index (foreign_structs, i);
+ g_free (module_name);
- if ( (strcmp (namespace, foreign_struct->namespace) == 0) &&
- (strcmp (name, foreign_struct->name) == 0)) {
- g_base_info_unref (base_info);
- return foreign_struct;
- }
+ if (module == NULL)
+ PyErr_Clear ();
+ else {
+ Py_DECREF (module);
+ result = do_lookup (namespace, name);
}
}
- g_base_info_unref (base_info);
+ if (result == NULL) {
+ PyErr_Format (PyExc_TypeError,
+ "Couldn't find conversion for foreign struct '%s.%s'",
+ namespace,
+ name);
+ }
- PyErr_Format (PyExc_TypeError, "Couldn't find conversion for foreign struct '%s.%s'", namespace, name);
- return NULL;
+ return result;
}
PyObject *
-pygi_struct_foreign_convert_to_g_argument (PyObject *value,
+pygi_struct_foreign_convert_to_g_argument (PyObject *value,
GITypeInfo *type_info,
GITransfer transfer,
GArgument *arg)
{
- PyGIForeignStruct *foreign_struct = pygi_struct_foreign_lookup (type_info);
+ GIBaseInfo *base_info = g_type_info_get_interface (type_info);
+ PyGIForeignStruct *foreign_struct = pygi_struct_foreign_lookup (base_info);
+ g_base_info_unref (base_info);
if (foreign_struct == NULL)
return NULL;
@@ -100,7 +126,10 @@ PyObject *
pygi_struct_foreign_convert_from_g_argument (GITypeInfo *type_info,
GArgument *arg)
{
- PyGIForeignStruct *foreign_struct = pygi_struct_foreign_lookup (type_info);
+ GIBaseInfo *base_info = g_type_info_get_interface (type_info);
+ PyGIForeignStruct *foreign_struct = pygi_struct_foreign_lookup (base_info);
+ g_base_info_unref (base_info);
+
if (foreign_struct == NULL)
return NULL;
@@ -109,11 +138,10 @@ pygi_struct_foreign_convert_from_g_argument (GITypeInfo *type_info,
}
PyObject *
-pygi_struct_foreign_release_g_argument (GITransfer transfer,
- GITypeInfo *type_info,
- GArgument *arg)
+pygi_struct_foreign_release (GIBaseInfo *base_info,
+ gpointer struct_)
{
- PyGIForeignStruct *foreign_struct = pygi_struct_foreign_lookup (type_info);
+ PyGIForeignStruct *foreign_struct = pygi_struct_foreign_lookup (base_info);
if (foreign_struct == NULL)
return NULL;
@@ -121,7 +149,7 @@ pygi_struct_foreign_release_g_argument (GITransfer transfer,
if (!foreign_struct->release_func)
Py_RETURN_NONE;
- if (!foreign_struct->release_func (transfer, type_info, arg))
+ if (!foreign_struct->release_func (base_info, struct_))
return NULL;
Py_RETURN_NONE;
@@ -132,7 +160,7 @@ pygi_register_foreign_struct_real (const char* namespace_,
const char* name,
PyGIArgOverrideToGArgumentFunc to_func,
PyGIArgOverrideFromGArgumentFunc from_func,
- PyGIArgOverrideReleaseGArgumentFunc release_func)
+ PyGIArgOverrideReleaseFunc release_func)
{
PyGIForeignStruct *new_struct = g_slice_new0 (PyGIForeignStruct);
new_struct->namespace = namespace_;
@@ -141,8 +169,5 @@ pygi_register_foreign_struct_real (const char* namespace_,
new_struct->from_func = from_func;
new_struct->release_func = release_func;
- if (foreign_structs == NULL)
- foreign_structs = g_ptr_array_new ();
-
g_ptr_array_add (foreign_structs, new_struct);
}
diff --git a/gi/pygi-foreign.h b/gi/pygi-foreign.h
index 9a35bd8..9582960 100644
--- a/gi/pygi-foreign.h
+++ b/gi/pygi-foreign.h
@@ -36,14 +36,13 @@ PyObject *pygi_struct_foreign_convert_to_g_argument (PyObject *value,
GArgument *arg);
PyObject *pygi_struct_foreign_convert_from_g_argument (GITypeInfo *type_info,
GArgument *arg);
-PyObject *pygi_struct_foreign_release_g_argument (GITransfer transfer,
- GITypeInfo *type_info,
- GArgument *arg);
+PyObject *pygi_struct_foreign_release (GITypeInfo *type_info,
+ gpointer struct_);
void pygi_register_foreign_struct_real (const char* namespace_,
const char* name,
PyGIArgOverrideToGArgumentFunc to_func,
PyGIArgOverrideFromGArgumentFunc from_func,
- PyGIArgOverrideReleaseGArgumentFunc release_func);
+ PyGIArgOverrideReleaseFunc release_func);
#endif /* __PYGI_FOREIGN_H__ */
diff --git a/gi/pygi-invoke.c b/gi/pygi-invoke.c
index a470003..022874e 100644
--- a/gi/pygi-invoke.c
+++ b/gi/pygi-invoke.c
@@ -639,6 +639,11 @@ _process_invocation_state (struct invocation_state *state,
GIInfoType info_type;
GITransfer transfer;
+ if (state->return_arg.v_pointer == NULL) {
+ PyErr_SetString (PyExc_TypeError, "constructor returned NULL");
+ return FALSE;
+ }
+
g_assert (state->n_py_args > 0);
py_type = (PyTypeObject *) PyTuple_GET_ITEM (py_args, 0);
@@ -662,18 +667,13 @@ _process_invocation_state (struct invocation_state *state,
type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *) info);
if (g_type_is_a (type, G_TYPE_BOXED)) {
- if (state->return_arg.v_pointer == NULL) {
- PyErr_SetString (PyExc_TypeError, "constructor returned NULL");
- break;
- }
g_warn_if_fail (transfer == GI_TRANSFER_EVERYTHING);
state->return_value = _pygi_boxed_new (py_type, state->return_arg.v_pointer, transfer == GI_TRANSFER_EVERYTHING);
+ } else if (type == G_TYPE_NONE && g_struct_info_is_foreign (info)) {
+ state->return_value =
+ pygi_struct_foreign_convert_from_g_argument (
+ state->return_type_info, state->return_arg.v_pointer);
} else if (g_type_is_a (type, G_TYPE_POINTER) || type == G_TYPE_NONE) {
- if (state->return_arg.v_pointer == NULL) {
- PyErr_SetString (PyExc_TypeError, "constructor returned NULL");
- break;
- }
-
if (transfer != GI_TRANSFER_NOTHING)
g_warning ("Transfer mode should be set to None for "
"struct types as there is no way to free "
diff --git a/gi/pygi-struct.c b/gi/pygi-struct.c
index 2f1ce42..e639c35 100644
--- a/gi/pygi-struct.c
+++ b/gi/pygi-struct.c
@@ -29,14 +29,22 @@
static void
_struct_dealloc (PyGIStruct *self)
{
+ GIBaseInfo *info = _pygi_object_get_gi_info (
+ (PyObject *) ( (PyObject *) self)->ob_type,
+ &PyGIStructInfo_Type);
+
PyObject_GC_UnTrack ( (PyObject *) self);
PyObject_ClearWeakRefs ( (PyObject *) self);
- if (self->free_on_dealloc) {
+ if (info != NULL && g_struct_info_is_foreign ( (GIStructInfo *) info)) {
+ pygi_struct_foreign_release (info, ( (PyGPointer *) self)->pointer);
+ } else if (self->free_on_dealloc) {
g_free ( ( (PyGPointer *) self)->pointer);
}
+ g_base_info_unref (info);
+
( (PyGPointer *) self)->ob_type->tp_free ( (PyObject *) self);
}
diff --git a/gi/pygi.h b/gi/pygi.h
index 0a8cbf5..92b7bae 100644
--- a/gi/pygi.h
+++ b/gi/pygi.h
@@ -57,9 +57,8 @@ typedef PyObject * (*PyGIArgOverrideToGArgumentFunc) (PyObject *value,
GArgument *arg);
typedef PyObject * (*PyGIArgOverrideFromGArgumentFunc) (GITypeInfo *type_info,
GArgument *arg);
-typedef PyObject * (*PyGIArgOverrideReleaseGArgumentFunc) (GITransfer transfer,
- GITypeInfo *type_info,
- GArgument *arg);
+typedef PyObject * (*PyGIArgOverrideReleaseFunc) (GITypeInfo *type_info,
+ gpointer struct_);
struct PyGI_API {
PyObject* (*type_import_by_g_type) (GType g_type);
@@ -67,7 +66,7 @@ struct PyGI_API {
const char* name,
PyGIArgOverrideToGArgumentFunc to_func,
PyGIArgOverrideFromGArgumentFunc from_func,
- PyGIArgOverrideReleaseGArgumentFunc release_func);
+ PyGIArgOverrideReleaseFunc release_func);
};
static struct PyGI_API *PyGI_API = NULL;
@@ -101,7 +100,7 @@ pygi_register_foreign_struct (const char* namespace_,
const char* name,
PyGIArgOverrideToGArgumentFunc to_func,
PyGIArgOverrideFromGArgumentFunc from_func,
- PyGIArgOverrideReleaseGArgumentFunc release_func)
+ PyGIArgOverrideReleaseFunc release_func)
{
if (_pygi_import() < 0) {
return NULL;
diff --git a/tests/test_everything.py b/tests/test_everything.py
index 69d1954..4e68b65 100644
--- a/tests/test_everything.py
+++ b/tests/test_everything.py
@@ -10,6 +10,7 @@ from sys import getrefcount
import cairo
from gi.repository import GObject
+from gi.repository import GLib
from gi.repository import Everything
class TestEverything(unittest.TestCase):
@@ -47,6 +48,13 @@ class TestEverything(unittest.TestCase):
self.assertEquals(surface.get_width(), 10)
self.assertEquals(surface.get_height(), 10)
+ def test_gvariant(self):
+ variant = GLib.Variant.new_int32(42);
+ self.assertEquals(variant.get_int32(), 42)
+
+ variant = GLib.Variant.new_strv(['mec', 'mac']);
+ self.assertEquals(variant.get_strv(), ['mec', 'mac'])
+
def test_floating(self):
Everything.TestFloating()
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]