[pygobject/gsoc2009: 11/160] Add nested structures support
- From: Simon van der Linden <svdlinden src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [pygobject/gsoc2009: 11/160] Add nested structures support
- Date: Fri, 14 Aug 2009 21:23:00 +0000 (UTC)
commit b45462fd373dbd4f6c024c9f21babf77b5af829c
Author: Simon van der Linden <simon vanderlinden student uclouvain be>
Date: Mon Jun 22 23:35:34 2009 +0200
Add nested structures support
In _wrap_g_field_info_set_value were added a conditional with a few
cases that are not handled by g_field_info_set_field. So far,
only structures are handled.
Ditto in _wrap_g_field_info_get_value.
In the Python base class for structures, the counterpart of __eq__, the
__ne__ magic, was needed too to ensure coherent comparisons.
girepository/bank-argument.c | 5 +
girepository/bank-info.c | 178 +++++++++++++++++++++++++++++++++++-------
girepository/btypes.py | 3 +
3 files changed, 157 insertions(+), 29 deletions(-)
---
diff --git a/girepository/bank-argument.c b/girepository/bank-argument.c
index 26c77dc..5700ae9 100644
--- a/girepository/bank-argument.c
+++ b/girepository/bank-argument.c
@@ -97,6 +97,11 @@ pyg_argument_from_pyobject(PyObject *object, GITypeInfo *type_info)
interface_type = g_base_info_get_type(interface_info);
if (interface_type == GI_INFO_TYPE_ENUM) {
arg.v_int = PyInt_AsLong(object);
+ } else if (interface_type == GI_INFO_TYPE_STRUCT || interface_type == GI_INFO_TYPE_BOXED) {
+ PyObject *py_buffer;
+ py_buffer = PyObject_GetAttrString(object, "__buffer__");
+ g_assert(py_buffer != NULL);
+ (*py_buffer->ob_type->tp_as_buffer->bf_getreadbuffer)(py_buffer, 0, &arg.v_pointer);
} else if (object == Py_None)
arg.v_pointer = NULL;
else
diff --git a/girepository/bank-info.c b/girepository/bank-info.c
index 2293b6d..9adafed 100644
--- a/girepository/bank-info.c
+++ b/girepository/bank-info.c
@@ -1039,43 +1039,102 @@ static PyObject *
_wrap_g_field_info_get_value(PyGIBaseInfo *self, PyObject *args)
{
PyObject *obj;
- void *buffer;
+ gpointer buffer;
GArgument value;
+ GIBaseInfo *container;
+ GIInfoType container_type;
GIFieldInfo *field_info;
+ GITypeInfo *field_type_info;
PyObject *retval;
+ retval = NULL;
+
field_info = (GIFieldInfo *)self->info;
if (!PyArg_ParseTuple(args, "O:TypeInfo.getValue", &obj))
return NULL;
- GIBaseInfo *container = g_base_info_get_container((GIBaseInfo *) self->info);
- GIInfoType container_type = g_base_info_get_type(container);
+ container = g_base_info_get_container((GIBaseInfo *)field_info);
+ container_type = g_base_info_get_type(container);
+
+ field_type_info = g_field_info_get_type(field_info);
if (container_type == GI_INFO_TYPE_STRUCT || container_type == GI_INFO_TYPE_BOXED) {
- PyObject *pybuffer = PyObject_GetAttrString(obj, "__buffer__");
- PyBufferProcs *buffer_procs = pybuffer->ob_type->tp_as_buffer;
- if (buffer_procs == NULL || buffer_procs->bf_getreadbuffer == 0) {
+ PyBufferProcs *py_buffer_procs;
+ PyObject *py_buffer;
+
+ py_buffer = PyObject_GetAttrString(obj, "__buffer__");
+ if (py_buffer == NULL) {
+ goto field_info_get_value_return;
+ }
+
+ py_buffer_procs = py_buffer->ob_type->tp_as_buffer;
+ if (py_buffer_procs == NULL || py_buffer_procs->bf_getreadbuffer == 0) {
+ Py_DECREF(py_buffer);
PyErr_SetString(PyExc_RuntimeError, "Failed to get buffer for struct");
- return NULL;
+ goto field_info_get_value_return;
}
- (*buffer_procs->bf_getreadbuffer)(pybuffer, 0, &buffer);
+
+ (*py_buffer_procs->bf_getreadbuffer)(py_buffer, 0, &buffer);
} else {
buffer = ((PyGObject *) obj)->obj;
- printf("obj: %p\n", buffer);
}
- if (!g_field_info_get_field (field_info, buffer, &value)) {
+ /* A few types are not handled by g_field_info_get_field, so do it here. */
+ if (!g_type_info_is_pointer(field_type_info) && g_type_info_get_tag(field_type_info) == GI_TYPE_TAG_INTERFACE) {
+ GIBaseInfo *interface_info;
+
+ if (!g_field_info_get_flags (field_info) & GI_FIELD_IS_READABLE) {
+ PyErr_SetString(PyExc_RuntimeError, "Field is not readable");
+ goto field_info_get_value_return;
+ }
+
+ interface_info = g_type_info_get_interface (field_type_info);
+ switch(g_base_info_get_type(interface_info))
+ {
+ case GI_INFO_TYPE_STRUCT:
+ {
+ gsize offset;
+ gsize size;
+
+ offset = g_field_info_get_offset(field_info);
+ size = g_struct_info_get_size((GIStructInfo *)interface_info);
+ g_assert(size > 0);
+
+ value.v_pointer = g_try_malloc(size);
+ if (value.v_pointer == NULL) {
+ PyErr_SetString(PyExc_MemoryError, "Failed to allocate memory");
+ break;
+ }
+ g_memmove(value.v_pointer, buffer + offset, size);
+ break;
+ }
+ case GI_INFO_TYPE_UNION:
+ case GI_INFO_TYPE_BOXED:
+ PyErr_SetString(PyExc_NotImplementedError, "Interface type not handled yet");
+ break;
+ default:
+ if (!g_field_info_get_field(field_info, buffer, &value)) {
+ PyErr_SetString(PyExc_RuntimeError, "Failed to get value for field");
+ }
+ }
+
+ g_base_info_unref(interface_info);
+
+ if (PyErr_Occurred()) {
+ goto field_info_get_value_return;
+ }
+ } else if (!g_field_info_get_field (field_info, buffer, &value)) {
PyErr_SetString(PyExc_RuntimeError, "Failed to get value for field");
- return NULL;
+ goto field_info_get_value_return;
}
retval = pyg_argument_to_pyobject (&value, g_field_info_get_type (field_info));
- if (retval == NULL) {
- return NULL;
- }
- Py_INCREF(retval);
+field_info_get_value_return:
+ g_base_info_unref((GIBaseInfo *)field_type_info);
+
+ Py_XINCREF(retval);
return retval;
}
@@ -1083,40 +1142,101 @@ static PyObject *
_wrap_g_field_info_set_value(PyGIBaseInfo *self, PyObject *args)
{
PyObject *obj;
- void *buffer;
+ PyObject *value;
+ gpointer buffer;
GArgument arg;
GIFieldInfo *field_info;
- PyObject *value;
+ GIBaseInfo *container;
+ GIInfoType container_type;
+ GITypeInfo *field_type_info;
+ PyObject *retval;
+
+ retval = Py_None;
field_info = (GIFieldInfo *)self->info;
if (!PyArg_ParseTuple(args, "OO:TypeInfo.setValue", &obj, &value))
return NULL;
- GIBaseInfo *container = g_base_info_get_container((GIBaseInfo *) self->info);
- GIInfoType container_type = g_base_info_get_type(container);
+ container = g_base_info_get_container((GIBaseInfo *) self->info);
+ container_type = g_base_info_get_type(container);
+
+ field_type_info = g_field_info_get_type(field_info);
if (container_type == GI_INFO_TYPE_STRUCT || container_type == GI_INFO_TYPE_BOXED) {
- PyObject *pybuffer = PyObject_GetAttrString(obj, "__buffer__");
- PyBufferProcs *buffer_procs = pybuffer->ob_type->tp_as_buffer;
- if (buffer_procs == NULL || buffer_procs->bf_getreadbuffer == 0) {
+ PyObject *py_buffer;
+ PyBufferProcs *py_buffer_procs;
+
+ py_buffer = PyObject_GetAttrString(obj, "__buffer__");
+ if (py_buffer == NULL) {
+ retval = NULL;
+ goto field_info_set_value_return;
+ }
+
+ py_buffer_procs = py_buffer->ob_type->tp_as_buffer;
+ if (py_buffer_procs == NULL || py_buffer_procs->bf_getreadbuffer == 0) {
+ Py_DECREF(py_buffer);
PyErr_SetString(PyExc_RuntimeError, "Failed to get buffer for struct");
- return NULL;
+ retval = NULL;
+ goto field_info_set_value_return;
}
- (*buffer_procs->bf_getreadbuffer)(pybuffer, 0, &buffer);
+
+ (*py_buffer_procs->bf_getreadbuffer)(py_buffer, 0, &buffer);
} else {
buffer = ((PyGObject *) obj)->obj;
}
- arg = pyg_argument_from_pyobject(value, g_field_info_get_type (field_info));
+ arg = pyg_argument_from_pyobject(value, field_type_info);
+
+ /* A few types are not handled by g_field_info_set_field, so do it here. */
+ if (!g_type_info_is_pointer(field_type_info) && g_type_info_get_tag(field_type_info) == GI_TYPE_TAG_INTERFACE) {
+ GIBaseInfo *interface_info;
- if (!g_field_info_set_field (field_info, buffer, &arg)) {
+ if (!g_field_info_get_flags (field_info) & GI_FIELD_IS_WRITABLE) {
+ PyErr_SetString(PyExc_RuntimeError, "Field is not writable");
+ retval = NULL;
+ goto field_info_set_value_return;
+ }
+
+ interface_info = g_type_info_get_interface (field_type_info);
+ switch (g_base_info_get_type(interface_info))
+ {
+ case GI_INFO_TYPE_STRUCT:
+ {
+ gsize offset;
+ gsize size;
+
+ offset = g_field_info_get_offset(field_info);
+ size = g_struct_info_get_size((GIStructInfo *)interface_info);
+ g_assert(size > 0);
+
+ g_memmove(buffer + offset, arg.v_pointer, size);
+ break;
+ }
+ case GI_INFO_TYPE_UNION:
+ case GI_INFO_TYPE_BOXED:
+ PyErr_SetString(PyExc_NotImplementedError, "Interface type not handled yet");
+ retval = NULL;
+ break;
+ default:
+ if (!g_field_info_set_field(field_info, buffer, &arg)) {
+ PyErr_SetString(PyExc_RuntimeError, "Failed to set value for field");
+ retval = NULL;
+ }
+ }
+
+ g_base_info_unref(interface_info);
+
+ } else if (!g_field_info_set_field(field_info, buffer, &arg)) {
PyErr_SetString(PyExc_RuntimeError, "Failed to set value for field");
- return NULL;
+ retval = NULL;
}
- Py_INCREF(Py_None);
- return Py_None;
+field_info_set_value_return:
+ g_base_info_unref((GIBaseInfo *)field_type_info);
+
+ Py_XINCREF(retval);
+ return retval;
}
static PyMethodDef _PyGIFieldInfo_methods[] = {
diff --git a/girepository/btypes.py b/girepository/btypes.py
index d7b6abd..d626b7a 100644
--- a/girepository/btypes.py
+++ b/girepository/btypes.py
@@ -302,3 +302,6 @@ class BaseBlob(object):
return False
return True
+ def __ne__(self, other):
+ return not self.__eq__(other)
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]