[pygobject/gsoc2009] Add support for structures registered as GPointers
- From: Simon van der Linden <svdlinden src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [pygobject/gsoc2009] Add support for structures registered as GPointers
- Date: Sat, 15 Aug 2009 13:35:05 +0000 (UTC)
commit 96ec342126cc8c3aa960b39d6f30455a908a4f66
Author: Simon van der Linden <svdlinden src gnome org>
Date: Sat Aug 15 15:15:36 2009 +0200
Add support for structures registered as GPointers
gi/gimodule.c | 6 +-
gi/module.py | 7 ++-
gi/pygi-argument.c | 10 ++-
gi/pygi-boxed.c | 177 -------------------------------------------
gi/pygi-boxed.h | 5 -
gi/pygi-info.c | 155 ++++++++++++++++++++++++++++++++++----
gi/pygi-info.h | 2 +
gi/pygi-private.h | 6 +-
gi/pygi.h | 19 +++--
gobject/gobjectmodule.c | 2 +
gobject/pygboxed.c | 25 ------
gobject/pygobject-private.h | 3 +
gobject/pygobject.h | 7 ++
gobject/pygpointer.c | 157 ++++++++++++++++++++++++++++++++------
tests/test_girepository.py | 2 +-
15 files changed, 320 insertions(+), 263 deletions(-)
---
diff --git a/gi/gimodule.c b/gi/gimodule.c
index 2557ea0..3ec456a 100644
--- a/gi/gimodule.c
+++ b/gi/gimodule.c
@@ -76,7 +76,7 @@ pygi_type_find_by_gi_info (GIBaseInfo *info)
}
GIBaseInfo *
-_pygi_object_get_gi_info (PyObject *object,
+pygi_object_get_gi_info (PyObject *object,
PyTypeObject *type)
{
PyObject *py_info;
@@ -133,8 +133,10 @@ static PyMethodDef _pygi_functions[] = {
};
struct PyGI_API PyGI_API = {
+ &PyGIStructInfo_Type,
+ pygi_g_struct_info_is_simple,
pygi_type_find_by_gi_info,
- pygi_boxed_new_from_type
+ pygi_object_get_gi_info
};
PyMODINIT_FUNC
diff --git a/gi/module.py b/gi/module.py
index 969c876..ef0956a 100644
--- a/gi/module.py
+++ b/gi/module.py
@@ -113,7 +113,12 @@ class DynamicModule(object):
bases = (gobject.GInterface,)
metaclass = GObjectMeta
elif isinstance(info, StructInfo):
- bases = (gobject.GBoxed,)
+ if g_type.is_a(gobject.TYPE_BOXED):
+ bases = (gobject.GBoxed,)
+ elif g_type.is_a(gobject.TYPE_POINTER) or g_type == gobject.TYPE_NONE:
+ bases = (gobject.GPointer,)
+ else:
+ raise TypeError, "unable to create a wrapper for %s.%s" % (info.get_namespace(), info.get_name())
metaclass = StructMeta
else:
raise NotImplementedError(info)
diff --git a/gi/pygi-argument.c b/gi/pygi-argument.c
index ee2b242..5e7b13b 100644
--- a/gi/pygi-argument.c
+++ b/gi/pygi-argument.c
@@ -1168,9 +1168,9 @@ array_item_error:
if (transfer == GI_TRANSFER_EVERYTHING) {
arg.v_pointer = g_boxed_copy(type, arg.v_pointer);
}
- } else if (type == G_TYPE_NONE) {
+ } else if (g_type_is_a(type, G_TYPE_POINTER) || type == G_TYPE_NONE) {
g_warn_if_fail(!is_pointer || transfer == GI_TRANSFER_NOTHING);
- arg.v_pointer = pyg_boxed_get(object, void);
+ arg.v_pointer = pyg_pointer_get(object, void);
} else {
PyErr_Format(PyExc_NotImplementedError, "structure type '%s' is not supported yet", g_type_name(type));
}
@@ -1691,6 +1691,8 @@ _pygi_argument_to_object (GArgument *arg,
} else if (g_type_is_a(type, G_TYPE_BOXED)) {
g_assert(is_pointer);
object = pyg_boxed_new(type, arg->v_pointer, FALSE, transfer == GI_TRANSFER_EVERYTHING);
+ } else if (g_type_is_a(type, G_TYPE_POINTER)) {
+ object = pyg_pointer_new(type, arg->v_pointer);
} else if (type == G_TYPE_NONE) {
PyObject *py_type;
@@ -1699,7 +1701,7 @@ _pygi_argument_to_object (GArgument *arg,
break;
}
- object = pygi_boxed_new_from_type((PyTypeObject *)py_type, arg->v_pointer,
+ object = pyg_pointer_new_from_type((PyTypeObject *)py_type, arg->v_pointer,
transfer == GI_TRANSFER_EVERYTHING);
Py_DECREF(py_type);
@@ -1980,7 +1982,7 @@ _pygi_argument_release (GArgument *arg,
}
} else if (g_type_is_a(type, G_TYPE_BOXED)) {
g_assert(is_pointer);
- } else if (type == G_TYPE_NONE) {
+ } else if (g_type_is_a(type, G_TYPE_POINTER) || type == G_TYPE_NONE) {
g_warn_if_fail(!is_pointer || transfer == GI_TRANSFER_NOTHING);
}
diff --git a/gi/pygi-boxed.c b/gi/pygi-boxed.c
index eb7fc31..55ed53e 100644
--- a/gi/pygi-boxed.c
+++ b/gi/pygi-boxed.c
@@ -25,181 +25,4 @@
#include <pygobject.h>
-gboolean
-_pygi_g_struct_info_is_simple (GIStructInfo *struct_info)
-{
- gboolean is_simple;
- gsize n_field_infos;
- gsize i;
-
- is_simple = TRUE;
-
- n_field_infos = g_struct_info_get_n_fields(struct_info);
-
- for (i = 0; i < n_field_infos && is_simple; i++) {
- GIFieldInfo *field_info;
- GITypeInfo *field_type_info;
- gboolean is_pointer;
-
- field_info = g_struct_info_get_field(struct_info, i);
- field_type_info = g_field_info_get_type(field_info);
- is_pointer = g_type_info_is_pointer(field_type_info);
-
- if (is_pointer) {
- is_simple = FALSE;
- } else {
- GITypeTag field_type_tag;
-
- field_type_tag = g_type_info_get_tag(field_type_info);
-
- switch (field_type_tag) {
- case GI_TYPE_TAG_BOOLEAN:
- case GI_TYPE_TAG_INT8:
- case GI_TYPE_TAG_UINT8:
- case GI_TYPE_TAG_INT16:
- case GI_TYPE_TAG_UINT16:
- case GI_TYPE_TAG_INT32:
- case GI_TYPE_TAG_UINT32:
- case GI_TYPE_TAG_SHORT:
- case GI_TYPE_TAG_USHORT:
- case GI_TYPE_TAG_INT:
- case GI_TYPE_TAG_UINT:
- case GI_TYPE_TAG_INT64:
- case GI_TYPE_TAG_UINT64:
- case GI_TYPE_TAG_LONG:
- case GI_TYPE_TAG_ULONG:
- case GI_TYPE_TAG_SSIZE:
- case GI_TYPE_TAG_SIZE:
- case GI_TYPE_TAG_FLOAT:
- case GI_TYPE_TAG_DOUBLE:
- case GI_TYPE_TAG_TIME_T:
- break;
- case GI_TYPE_TAG_VOID:
- case GI_TYPE_TAG_GTYPE:
- case GI_TYPE_TAG_ERROR:
- case GI_TYPE_TAG_UTF8:
- case GI_TYPE_TAG_FILENAME:
- case GI_TYPE_TAG_ARRAY:
- case GI_TYPE_TAG_GLIST:
- case GI_TYPE_TAG_GSLIST:
- case GI_TYPE_TAG_GHASH:
- /* Should have been catched by is_pointer above. */
- g_assert_not_reached();
- break;
- case GI_TYPE_TAG_INTERFACE:
- {
- GIBaseInfo *info;
- GIInfoType info_type;
-
- info = g_type_info_get_interface(field_type_info);
- info_type = g_base_info_get_type(info);
-
- switch (info_type) {
- case GI_INFO_TYPE_BOXED:
- case GI_INFO_TYPE_STRUCT:
- is_simple = _pygi_g_struct_info_is_simple((GIStructInfo *)info);
- break;
- case GI_INFO_TYPE_UNION:
- /* TODO */
- is_simple = FALSE;
- break;
- case GI_INFO_TYPE_ENUM:
- case GI_INFO_TYPE_FLAGS:
- break;
- case GI_INFO_TYPE_OBJECT:
- case GI_INFO_TYPE_VFUNC:
- case GI_INFO_TYPE_CALLBACK:
- case GI_INFO_TYPE_INVALID:
- case GI_INFO_TYPE_INTERFACE:
- case GI_INFO_TYPE_FUNCTION:
- case GI_INFO_TYPE_CONSTANT:
- case GI_INFO_TYPE_ERROR_DOMAIN:
- case GI_INFO_TYPE_VALUE:
- case GI_INFO_TYPE_SIGNAL:
- case GI_INFO_TYPE_PROPERTY:
- case GI_INFO_TYPE_FIELD:
- case GI_INFO_TYPE_ARG:
- case GI_INFO_TYPE_TYPE:
- case GI_INFO_TYPE_UNRESOLVED:
- is_simple = FALSE;
- break;
- }
-
- g_base_info_unref(info);
- break;
- }
- }
- }
-
- g_base_info_unref((GIBaseInfo *)field_type_info);
- g_base_info_unref((GIBaseInfo *)field_info);
- }
-
- return is_simple;
-}
-
-PyObject *
-pygi_boxed_new_from_type (PyTypeObject *type,
- gpointer pointer,
- gboolean own_pointer)
-{
- GIBaseInfo *info;
- GIInfoType info_type;
- GType g_type;
- PyGBoxed *self = NULL;
-
- info = _pygi_object_get_gi_info((PyObject *)type, &PyGIRegisteredTypeInfo_Type);
- if (info == NULL) {
- if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
- PyErr_Format(PyExc_TypeError, "cannot create '%s' instances", type->tp_name);
- }
- return NULL;
- }
-
- info_type = g_base_info_get_type(info);
- g_type = g_registered_type_info_get_g_type((GIRegisteredTypeInfo *)info);
-
- if (pointer == NULL) {
- if (info_type == GI_INFO_TYPE_STRUCT && !g_type_is_a(g_type, G_TYPE_BOXED)) {
- gboolean is_simple;
- gsize size;
-
- is_simple = _pygi_g_struct_info_is_simple((GIStructInfo *)info);
- if (!is_simple) {
- PyErr_Format(PyExc_TypeError,
- "cannot create '%s' instances; needs a specific constructor", type->tp_name);
- goto out;
- }
-
- size = g_struct_info_get_size((GIStructInfo *)info);
-
- pointer = g_try_malloc(size);
- if (pointer == NULL) {
- PyErr_NoMemory();
- goto out;
- }
-
- own_pointer = TRUE;
- } else {
- PyErr_Format(PyExc_TypeError,
- "cannot create '%s' instances; needs a specific constructor", type->tp_name);
- goto out;
- }
- }
-
- self = (PyGBoxed *)type->tp_alloc(type, 0);
- if (self == NULL) {
- g_free(pointer);
- goto out;
- }
-
- self->boxed = pointer;
- self->gtype = g_type;
- self->free_on_dealloc = own_pointer;
-
-out:
- g_base_info_unref(info);
-
- return (PyObject *)self;
-}
diff --git a/gi/pygi-boxed.h b/gi/pygi-boxed.h
index ef23132..de6ecdd 100644
--- a/gi/pygi-boxed.h
+++ b/gi/pygi-boxed.h
@@ -26,14 +26,9 @@
G_BEGIN_DECLS
-PyObject* pygi_boxed_new_from_type (PyTypeObject *type,
- gpointer pointer,
- gboolean own_pointer);
-
/* Private */
-gboolean _pygi_g_struct_info_is_simple (GIStructInfo *struct_info);
G_END_DECLS
diff --git a/gi/pygi-info.c b/gi/pygi-info.c
index 1cf2e1a..ceb81a2 100644
--- a/gi/pygi-info.c
+++ b/gi/pygi-info.c
@@ -583,8 +583,22 @@ _wrap_g_function_info_invoke (PyGIBaseInfo *self,
g_assert_not_reached();
break;
case GI_INFO_TYPE_STRUCT:
- in_args[0].v_pointer = pyg_boxed_get(py_arg, void);
+ {
+ GType type;
+
+ type = g_registered_type_info_get_g_type((GIRegisteredTypeInfo *)container_info);
+
+ if (g_type_is_a(type, G_TYPE_BOXED)) {
+ in_args[0].v_pointer = pyg_boxed_get(py_arg, void);
+ } else if (g_type_is_a(type, G_TYPE_POINTER) || type == G_TYPE_NONE) {
+ in_args[0].v_pointer = pyg_pointer_get(py_arg, void);
+ } else {
+ PyErr_Format(PyExc_TypeError, "unable to convert an instance of '%s'", g_type_name(type));
+ goto return_;
+ }
+
break;
+ }
case GI_INFO_TYPE_OBJECT:
case GI_INFO_TYPE_INTERFACE:
in_args[0].v_pointer = pygobject_get(py_arg);
@@ -806,20 +820,18 @@ _wrap_g_function_info_invoke (PyGIBaseInfo *self,
type = g_registered_type_info_get_g_type((GIRegisteredTypeInfo *)info);
- if (transfer == GI_TRANSFER_EVERYTHING && !g_type_is_a(type, G_TYPE_BOXED)) {
- gboolean is_simple;
-
- is_simple = _pygi_g_struct_info_is_simple((GIStructInfo *)info);
-
- if (is_simple) {
- PyErr_Format(PyExc_TypeError,
- "cannot create '%s' instances; non-boxed simple structures do not accept specific constructors",
- py_type->tp_name);
- /* TODO */
- goto return_;
- }
+ if (g_type_is_a(type, G_TYPE_BOXED)) {
+ g_warn_if_fail(transfer == GI_TRANSFER_EVERYTHING);
+ return_value = pyg_boxed_new(type, return_arg.v_pointer, FALSE, transfer == GI_TRANSFER_EVERYTHING);
+ } else if (g_type_is_a(type, G_TYPE_POINTER) || type == G_TYPE_NONE) {
+ g_warn_if_fail(transfer == GI_TRANSFER_NOTHING);
+ return_value = pyg_pointer_new_from_type(py_type, return_arg.v_pointer, transfer == GI_TRANSFER_EVERYTHING);
+ } else {
+ PyErr_Format(PyExc_TypeError, "cannot create '%s' instances", py_type->tp_name);
+ /* TODO */
+ goto return_;
}
- return_value = pygi_boxed_new_from_type(py_type, return_arg.v_pointer, transfer == GI_TRANSFER_EVERYTHING);
+
break;
}
case GI_INFO_TYPE_OBJECT:
@@ -1106,6 +1118,119 @@ static PyMethodDef _PyGIStructInfo_methods[] = {
{ NULL, NULL, 0 }
};
+gboolean
+pygi_g_struct_info_is_simple (GIStructInfo *struct_info)
+{
+ gboolean is_simple;
+ gsize n_field_infos;
+ gsize i;
+
+ is_simple = TRUE;
+
+ n_field_infos = g_struct_info_get_n_fields(struct_info);
+
+ for (i = 0; i < n_field_infos && is_simple; i++) {
+ GIFieldInfo *field_info;
+ GITypeInfo *field_type_info;
+ gboolean is_pointer;
+
+ field_info = g_struct_info_get_field(struct_info, i);
+ field_type_info = g_field_info_get_type(field_info);
+ is_pointer = g_type_info_is_pointer(field_type_info);
+
+ if (is_pointer) {
+ is_simple = FALSE;
+ } else {
+ GITypeTag field_type_tag;
+
+ field_type_tag = g_type_info_get_tag(field_type_info);
+
+ switch (field_type_tag) {
+ case GI_TYPE_TAG_BOOLEAN:
+ case GI_TYPE_TAG_INT8:
+ case GI_TYPE_TAG_UINT8:
+ case GI_TYPE_TAG_INT16:
+ case GI_TYPE_TAG_UINT16:
+ case GI_TYPE_TAG_INT32:
+ case GI_TYPE_TAG_UINT32:
+ case GI_TYPE_TAG_SHORT:
+ case GI_TYPE_TAG_USHORT:
+ case GI_TYPE_TAG_INT:
+ case GI_TYPE_TAG_UINT:
+ case GI_TYPE_TAG_INT64:
+ case GI_TYPE_TAG_UINT64:
+ case GI_TYPE_TAG_LONG:
+ case GI_TYPE_TAG_ULONG:
+ case GI_TYPE_TAG_SSIZE:
+ case GI_TYPE_TAG_SIZE:
+ case GI_TYPE_TAG_FLOAT:
+ case GI_TYPE_TAG_DOUBLE:
+ case GI_TYPE_TAG_TIME_T:
+ break;
+ case GI_TYPE_TAG_VOID:
+ case GI_TYPE_TAG_GTYPE:
+ case GI_TYPE_TAG_ERROR:
+ case GI_TYPE_TAG_UTF8:
+ case GI_TYPE_TAG_FILENAME:
+ case GI_TYPE_TAG_ARRAY:
+ case GI_TYPE_TAG_GLIST:
+ case GI_TYPE_TAG_GSLIST:
+ case GI_TYPE_TAG_GHASH:
+ /* Should have been catched by is_pointer above. */
+ g_assert_not_reached();
+ break;
+ case GI_TYPE_TAG_INTERFACE:
+ {
+ GIBaseInfo *info;
+ GIInfoType info_type;
+
+ info = g_type_info_get_interface(field_type_info);
+ info_type = g_base_info_get_type(info);
+
+ switch (info_type) {
+ case GI_INFO_TYPE_BOXED:
+ case GI_INFO_TYPE_STRUCT:
+ is_simple = pygi_g_struct_info_is_simple((GIStructInfo *)info);
+ break;
+ case GI_INFO_TYPE_UNION:
+ /* TODO */
+ is_simple = FALSE;
+ break;
+ case GI_INFO_TYPE_ENUM:
+ case GI_INFO_TYPE_FLAGS:
+ break;
+ case GI_INFO_TYPE_OBJECT:
+ case GI_INFO_TYPE_VFUNC:
+ case GI_INFO_TYPE_CALLBACK:
+ case GI_INFO_TYPE_INVALID:
+ case GI_INFO_TYPE_INTERFACE:
+ case GI_INFO_TYPE_FUNCTION:
+ case GI_INFO_TYPE_CONSTANT:
+ case GI_INFO_TYPE_ERROR_DOMAIN:
+ case GI_INFO_TYPE_VALUE:
+ case GI_INFO_TYPE_SIGNAL:
+ case GI_INFO_TYPE_PROPERTY:
+ case GI_INFO_TYPE_FIELD:
+ case GI_INFO_TYPE_ARG:
+ case GI_INFO_TYPE_TYPE:
+ case GI_INFO_TYPE_UNRESOLVED:
+ is_simple = FALSE;
+ break;
+ }
+
+ g_base_info_unref(info);
+ break;
+ }
+ }
+ }
+
+ g_base_info_unref((GIBaseInfo *)field_type_info);
+ g_base_info_unref((GIBaseInfo *)field_info);
+ }
+
+ return is_simple;
+}
+
/* EnumInfo */
_PyGI_DEFINE_INFO_TYPE("EnumInfo", GIEnumInfo, PyGIRegisteredTypeInfo_Type);
@@ -1541,7 +1666,7 @@ _wrap_g_field_info_set_value (PyGIBaseInfo *self,
gsize offset;
gssize size;
- is_simple = _pygi_g_struct_info_is_simple((GIStructInfo *)info);
+ is_simple = pygi_g_struct_info_is_simple((GIStructInfo *)info);
if (!is_simple) {
PyErr_SetString(PyExc_TypeError,
diff --git a/gi/pygi-info.h b/gi/pygi-info.h
index c24fa11..aecf96e 100644
--- a/gi/pygi-info.h
+++ b/gi/pygi-info.h
@@ -28,6 +28,8 @@
G_BEGIN_DECLS
+gboolean pygi_g_struct_info_is_simple (GIStructInfo *struct_info);
+
/* Private */
diff --git a/gi/pygi-private.h b/gi/pygi-private.h
index a76cffc..e928c09 100644
--- a/gi/pygi-private.h
+++ b/gi/pygi-private.h
@@ -52,11 +52,11 @@ PyObject* pygi_type_find_by_name (const char *namespace_,
const char *name);
PyObject* pygi_type_find_by_gi_info (GIBaseInfo *info);
+GIBaseInfo* pygi_object_get_gi_info (PyObject *object,
+ PyTypeObject *type);
-/* Private */
-GIBaseInfo* _pygi_object_get_gi_info (PyObject *object,
- PyTypeObject *type);
+/* Private */
#define _PyGI_ERROR_PREFIX(format, ...) G_STMT_START { \
diff --git a/gi/pygi.h b/gi/pygi.h
index 7681fc5..b809da3 100644
--- a/gi/pygi.h
+++ b/gi/pygi.h
@@ -43,13 +43,14 @@ typedef struct {
struct PyGI_API {
+ /* Info */
+ PyTypeObject *StructInfo_Type;
+ gboolean (*g_struct_info_is_simple) (GIStructInfo *struct_info);
+
/* Misc */
PyObject* (*type_find_by_gi_info) (GIBaseInfo *info);
-
- /* Boxed */
- PyObject* (*boxed_new_from_type) (PyTypeObject *type,
- gpointer pointer,
- gboolean own_pointer);
+ GIBaseInfo* (*object_get_gi_info) (PyObject *object,
+ PyTypeObject *type);
};
@@ -57,11 +58,13 @@ struct PyGI_API {
static struct PyGI_API *PyGI_API = NULL;
+/* Info */
+#define PyGIStructInfo_Type (*PyGI_API->StructInfo_Type)
+#define pygi_g_struct_info_is_simple (PyGI_API->g_struct_info_is_simple)
+
/* Misc */
#define pygi_type_find_by_gi_info (PyGI_API->type_find_by_gi_info)
-
-/* Boxed */
-#define pygi_boxed_new_from_type (PyGI_API->boxed_new_from_type)
+#define pygi_object_get_gi_info (PyGI_API->object_get_gi_info)
static int
diff --git a/gobject/gobjectmodule.c b/gobject/gobjectmodule.c
index 7c77d3e..df018ba 100644
--- a/gobject/gobjectmodule.c
+++ b/gobject/gobjectmodule.c
@@ -2579,6 +2579,8 @@ struct _PyGObject_Functions pygobject_api_functions = {
pygobject_new_from_type,
&PyGInterface_Type,
+
+ pyg_pointer_new_from_type
};
/* for addon libraries ... */
diff --git a/gobject/pygboxed.c b/gobject/pygboxed.c
index 7fe05d4..6dc7c6f 100644
--- a/gobject/pygboxed.c
+++ b/gobject/pygboxed.c
@@ -215,26 +215,6 @@ pyg_boxed_new(GType boxed_type, gpointer boxed, gboolean copy_boxed,
return (PyObject *)self;
}
-#if HAVE_PYGI_H
-static PyObject *
-pyg_boxed_new_ (PyTypeObject *type,
- PyObject *args,
- PyObject *kwds)
-{
- static char *kwlist[] = { NULL };
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "", kwlist)) {
- return NULL;
- }
-
- if (pygi_import() < 0) {
- return NULL;
- }
-
- return pygi_boxed_new_from_type(type, NULL, TRUE);
-}
-#endif /* HAVE_PYGI_H */
-
void
pygobject_boxed_register_types(PyObject *d)
{
@@ -248,16 +228,11 @@ pygobject_boxed_register_types(PyObject *d)
PyGBoxed_Type.tp_methods = pygboxed_methods;
PyGBoxed_Type.tp_free = (freefunc)pyg_boxed_free;
PyGBoxed_Type.tp_hash = (hashfunc)pyg_boxed_hash;
-#if HAVE_PYGI_H
- PyGBoxed_Type.tp_new = (newfunc)pyg_boxed_new_;
-#endif
PYGOBJECT_REGISTER_GTYPE(d, PyGBoxed_Type, "GBoxed", G_TYPE_BOXED);
-#if !HAVE_PYGI_H
/* We don't want instances to be created in Python, but
* PYGOBJECT_REGISTER_GTYPE assigned PyObject_GenericNew as instance
* constructor. It's not too late to revert it to NULL, though. */
PyGBoxed_Type.tp_new = (newfunc)NULL;
-#endif
}
diff --git a/gobject/pygobject-private.h b/gobject/pygobject-private.h
index a106ca8..c0fcf66 100644
--- a/gobject/pygobject-private.h
+++ b/gobject/pygobject-private.h
@@ -171,6 +171,9 @@ extern PyTypeObject PyGPointer_Type;
void pyg_register_pointer (PyObject *dict, const gchar *class_name,
GType pointer_type, PyTypeObject *type);
PyObject * pyg_pointer_new (GType pointer_type, gpointer pointer);
+PyObject * pyg_pointer_new_from_type (PyTypeObject *type,
+ gpointer pointer,
+ gboolean free_on_dealloc);
const gchar * pyg_constant_strip_prefix(const gchar *name, const gchar *strip_prefix);
diff --git a/gobject/pygobject.h b/gobject/pygobject.h
index fa963a2..cedd467 100644
--- a/gobject/pygobject.h
+++ b/gobject/pygobject.h
@@ -64,6 +64,7 @@ typedef struct {
PyObject_HEAD
gpointer pointer;
GType gtype;
+ gboolean free_on_dealloc;
} PyGPointer;
#define pyg_pointer_get(v,t) ((t *)((PyGPointer *)(v))->pointer)
@@ -207,6 +208,10 @@ struct _PyGObject_Functions {
gboolean sink);
PyTypeObject *interface_type;
+
+ PyObject* (*pointer_new_from_type) (PyTypeObject *type,
+ gpointer pointer,
+ gboolean free_on_dealloc);
};
#ifndef _INSIDE_PYGOBJECT_
@@ -280,6 +285,8 @@ struct _PyGObject_Functions *_PyGObject_API;
#define PyGInterface_Type (*_PyGObject_API->interface_type)
+#define pyg_pointer_new_from_type (_PyGObject_API->pointer_new_from_type)
+
#define pyg_block_threads() G_STMT_START { \
if (_PyGObject_API->block_threads != NULL) \
(* _PyGObject_API->block_threads)(); \
diff --git a/gobject/pygpointer.c b/gobject/pygpointer.c
index ee0a8da..b0341c9 100644
--- a/gobject/pygpointer.c
+++ b/gobject/pygpointer.c
@@ -25,6 +25,9 @@
#endif
#include <pyglib.h>
+#if HAVE_PYGI_H
+# include <pygi.h>
+#endif
#include "pygobject-private.h"
#include "pygpointer.h"
@@ -35,6 +38,9 @@ PYGLIB_DEFINE_TYPE("gobject.GPointer", PyGPointer_Type, PyGPointer);
static void
pyg_pointer_dealloc(PyGPointer *self)
{
+ if (self->free_on_dealloc) {
+ g_free(self->pointer);
+ }
Py_TYPE(self)->tp_free((PyObject *)self);
}
@@ -62,23 +68,6 @@ pyg_pointer_repr(PyGPointer *self)
return _PyUnicode_FromString(buf);
}
-static int
-pyg_pointer_init(PyGPointer *self, PyObject *args, PyObject *kwargs)
-{
- gchar buf[512];
-
- if (!PyArg_ParseTuple(args, ":GPointer.__init__"))
- return -1;
-
- self->pointer = NULL;
- self->gtype = 0;
-
- g_snprintf(buf, sizeof(buf), "%s can not be constructed",
- Py_TYPE(self)->tp_name);
- PyErr_SetString(PyExc_NotImplementedError, buf);
- return -1;
-}
-
static void
pyg_pointer_free(PyObject *op)
{
@@ -125,6 +114,33 @@ pyg_register_pointer(PyObject *dict, const gchar *class_name,
PyDict_SetItemString(dict, (char *)class_name, (PyObject *)type);
}
+PyObject *
+pyg_pointer_new_from_type (PyTypeObject *type,
+ gpointer pointer,
+ gboolean free_on_dealloc)
+{
+ PyGPointer *self;
+ GType g_type;
+
+ if (!PyType_IsSubtype(type, &PyGPointer_Type)) {
+ PyErr_SetString(PyExc_TypeError, "must be a subtype of gobject.GPointer");
+ return NULL;
+ }
+
+ self = (PyGPointer *)type->tp_alloc(type, 0);
+ if (self == NULL) {
+ return NULL;
+ }
+
+ g_type = pyg_type_from_object((PyObject *)type);
+
+ self->pointer = pointer;
+ self->gtype = g_type;
+ self->free_on_dealloc = free_on_dealloc;
+
+ return (PyObject *)self;
+}
+
/**
* pyg_pointer_new:
* @pointer_type: the GType of the pointer value.
@@ -155,21 +171,107 @@ pyg_pointer_new(GType pointer_type, gpointer pointer)
}
tp = g_type_get_qdata(pointer_type, pygpointer_class_key);
+
+#if HAVE_PYGI_H
+ if (tp == NULL) {
+ GIRepository *repository;
+ GIBaseInfo *info;
+
+ repository = g_irepository_get_default();
+
+ info = g_irepository_find_by_gtype(repository, pointer_type);
+
+ if (info != NULL) {
+ if (pygi_import() < 0) {
+ PyErr_WarnEx(NULL, "unable to import gi", 1);
+ PyErr_Clear();
+ } else {
+ tp = (PyTypeObject *)pygi_type_find_by_gi_info(info);
+ g_base_info_unref(info);
+ if (tp == NULL) {
+ PyErr_Clear();
+ } else {
+ /* Note: The type is registered, so at least a reference remains. */
+ Py_DECREF((PyObject *)tp);
+ }
+ }
+ }
+ }
+#endif
+
if (!tp)
tp = (PyTypeObject *)&PyGPointer_Type; /* fallback */
- self = PyObject_NEW(PyGPointer, tp);
+
+ self = (PyGPointer *)pyg_pointer_new_from_type(tp, pointer, FALSE);
pyglib_gil_state_release(state);
- if (self == NULL)
- return NULL;
+ if (self == NULL) {
+ return NULL;
+ }
- self->pointer = pointer;
+ /* In case the g_type has no wrapper, we don't want self->gtype to be G_TYPE_POINTER. */
self->gtype = pointer_type;
return (PyObject *)self;
}
+
+#if HAVE_PYGI_H
+static PyObject *
+_pyg_pointer_new (PyTypeObject *type,
+ PyObject *args,
+ PyObject *kwargs)
+{
+ static char *kwlist[] = { NULL };
+
+ GIBaseInfo *info;
+ gboolean is_simple;
+ gsize size;
+ gpointer pointer;
+ PyObject *self = NULL;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "", kwlist)) {
+ return NULL;
+ }
+
+ if (pygi_import() < 0) {
+ return NULL;
+ }
+
+ info = pygi_object_get_gi_info((PyObject *)type, &PyGIStructInfo_Type);
+ if (info == NULL) {
+ if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
+ PyErr_Format(PyExc_TypeError, "cannot create '%s' instances", type->tp_name);
+ }
+ return NULL;
+ }
+
+ is_simple = pygi_g_struct_info_is_simple((GIStructInfo *)info);
+ if (!is_simple) {
+ PyErr_Format(PyExc_TypeError, "cannot create '%s' instances", type->tp_name);
+ goto out;
+ }
+
+ size = g_struct_info_get_size((GIStructInfo *)info);
+ pointer = g_try_malloc(size);
+ if (pointer == NULL) {
+ PyErr_NoMemory();
+ goto out;
+ }
+
+ self = pyg_pointer_new_from_type(type, pointer, TRUE);
+ if (self == NULL) {
+ g_free(pointer);
+ }
+
+out:
+ g_base_info_unref(info);
+
+ return (PyObject *)self;
+}
+#endif
+
void
pygobject_pointer_register_types(PyObject *d)
{
@@ -180,7 +282,18 @@ pygobject_pointer_register_types(PyObject *d)
PyGPointer_Type.tp_repr = (reprfunc)pyg_pointer_repr;
PyGPointer_Type.tp_hash = (hashfunc)pyg_pointer_hash;
PyGPointer_Type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE;
- PyGPointer_Type.tp_init = (initproc)pyg_pointer_init;
PyGPointer_Type.tp_free = (freefunc)pyg_pointer_free;
+
+#if HAVE_PYGI_H
+ PyGPointer_Type.tp_new = (newfunc)_pyg_pointer_new;
+#endif
+
PYGOBJECT_REGISTER_GTYPE(d, PyGPointer_Type, "GPointer", G_TYPE_POINTER);
+
+#if !HAVE_PYGI_H
+ /* We don't want instances to be created in Python, but
+ * PYGOBJECT_REGISTER_GTYPE assigned PyObject_GenericNew as instance
+ * constructor. It's not too late to revert it to NULL, though. */
+ PyGPointer_Type.tp_new = (newfunc)NULL;
+#endif
}
diff --git a/tests/test_girepository.py b/tests/test_girepository.py
index 3b59f0c..d71053d 100644
--- a/tests/test_girepository.py
+++ b/tests/test_girepository.py
@@ -539,7 +539,7 @@ class TestGIEverything(unittest.TestCase):
def testStructA(self):
# Test inheritance.
- self.assertTrue(issubclass(Everything.TestStructA, gobject.GBoxed))
+ self.assertTrue(issubclass(Everything.TestStructA, gobject.GPointer))
# Test instanciation.
a = Everything.TestStructA()
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]