[pybank] Implement support for struct fields
- From: Johan Dahlin <johan src gnome org>
- To: svn-commits-list gnome org
- Subject: [pybank] Implement support for struct fields
- Date: Tue, 2 Jun 2009 10:43:57 -0400 (EDT)
commit 9491dcb53777415e91a137fa4e6076fbc31b4b24
Author: Tomeu Vizoso <tomeu sugarlabs org>
Date: Fri May 8 11:23:49 2009 +0200
Implement support for struct fields
---
bank/bank-argument.c | 16 ++++--
bank/bank-info.c | 127 +++++++++++++++++++++++++++++++++++++++++++++++-
bank/bank.h | 2 +-
bank/btypes.py | 40 ++++++++++-----
everything_unittest.py | 6 ++
5 files changed, 170 insertions(+), 21 deletions(-)
diff --git a/bank/bank-argument.c b/bank/bank-argument.c
index a4265d4..ecd3def 100644
--- a/bank/bank-argument.c
+++ b/bank/bank-argument.c
@@ -23,13 +23,11 @@
GArgument
-pyg_argument_from_pyobject(PyObject *object, GIArgInfo *info)
+pyg_argument_from_pyobject(PyObject *object, GITypeInfo *type_info)
{
- GITypeInfo *type_info;
GArgument arg;
GITypeTag type_tag;
- type_info = g_arg_info_get_type(info);
type_tag = g_type_info_get_tag((GITypeInfo*)type_info);
switch (type_tag) {
case GI_TYPE_TAG_VOID:
@@ -99,7 +97,6 @@ pyg_argument_from_pyobject(PyObject *object, GIArgInfo *info)
g_type_tag_to_string(type_tag));
break;
}
- g_base_info_unref((GIBaseInfo*)type_info);
return arg;
}
@@ -132,6 +129,11 @@ pyg_argument_to_pyobject(GArgument *arg, GITypeInfo *type_info)
PyObject_GC_Track(obj);
Py_INCREF(obj);
return obj;
+ } else if (interface_type == GI_INFO_TYPE_ENUM) {
+ g_warning("pyg_argument_to_pyobject: enums not implemented");
+ obj = Py_None;
+ Py_INCREF(obj);
+ return obj;
} else if ( arg->v_pointer == NULL ) {
obj = Py_None;
Py_INCREF(obj);
@@ -152,7 +154,7 @@ pyg_argument_to_pyobject(GArgument *arg, GITypeInfo *type_info)
obj = Py_None;
break;
case GI_TYPE_TAG_BOOLEAN:
- obj = PyBool_FromLong(arg->v_int);
+ obj = PyBool_FromLong(arg->v_boolean);
break;
case GI_TYPE_TAG_UINT8:
obj = PyInt_FromLong(arg->v_uint8);
@@ -167,9 +169,11 @@ pyg_argument_to_pyobject(GArgument *arg, GITypeInfo *type_info)
obj = PyLong_FromUnsignedLongLong(arg->v_uint64);
break;
case GI_TYPE_TAG_INT:
- case GI_TYPE_TAG_INT8:
obj = PyInt_FromLong(arg->v_int);
break;
+ case GI_TYPE_TAG_INT8:
+ obj = PyInt_FromLong(arg->v_int8);
+ break;
case GI_TYPE_TAG_INT16:
obj = PyInt_FromLong(arg->v_int16);
break;
diff --git a/bank/bank-info.c b/bank/bank-info.c
index 62f3b5b..e751584 100644
--- a/bank/bank-info.c
+++ b/bank/bank-info.c
@@ -240,6 +240,9 @@ pyg_info_new(void *info)
case GI_INFO_TYPE_VALUE:
tp = &PyGIValueInfo_Type;
break;
+ case GI_INFO_TYPE_FIELD:
+ tp = &PyGIFieldInfo_Type;
+ break;
default:
g_print ("Unhandled GIInfoType: %d\n", type_info);
Py_INCREF(Py_None);
@@ -383,6 +386,8 @@ _wrap_g_function_info_invoke(PyGIBaseInfo *self, PyObject *args)
in_args = g_newa(GArgument, expected_in_argc);
out_args = g_newa(GArgument, expected_out_argc);
/* each out arg is a pointer, they point to these values */
+ /* FIXME: This will break for caller-allocates funcs:
+ http://bugzilla.gnome.org/show_bug.cgi?id=573314 */
out_values = g_newa(GArgument, expected_out_argc);
failed = FALSE;
@@ -428,7 +433,7 @@ _wrap_g_function_info_invoke(PyGIBaseInfo *self, PyObject *args)
if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) {
py_arg = PyTuple_GetItem(args, i);
- GArgument in_value = pyg_argument_from_pyobject(py_arg, arg_info);
+ GArgument in_value = pyg_argument_from_pyobject(py_arg, g_arg_info_get_type(arg_info));
++argv_pos;
@@ -608,6 +613,27 @@ static PyMethodDef _PyGIRegisteredTypeInfo_methods[] = {
NEW_CLASS("StructInfo", GIStructInfo);
static PyObject *
+_wrap_g_struct_info_get_fields(PyGIBaseInfo *self)
+{
+ int i, length;
+ PyObject *retval;
+
+ g_base_info_ref(self->info);
+ length = g_struct_info_get_n_fields((GIStructInfo*)self->info);
+ retval = PyTuple_New(length);
+
+ for (i = 0; i < length; i++) {
+ GIFieldInfo *field;
+ field = g_struct_info_get_field((GIStructInfo*)self->info, i);
+ PyTuple_SetItem(retval, i, pyg_info_new(field));
+ g_base_info_unref((GIBaseInfo*)field);
+ }
+ g_base_info_unref(self->info);
+
+ return retval;
+}
+
+static PyObject *
_wrap_g_struct_info_get_methods(PyGIBaseInfo *self)
{
int i, length;
@@ -628,8 +654,107 @@ _wrap_g_struct_info_get_methods(PyGIBaseInfo *self)
return retval;
}
+static PyObject *
+_wrap_g_struct_info_new_buffer(PyGIBaseInfo *self)
+{
+ gsize size = g_struct_info_get_size ((GIStructInfo*)self->info);
+ PyObject *buffer = PyBuffer_New (size);
+ Py_INCREF(buffer);
+ return buffer;
+}
+
+static PyObject *
+_wrap_g_struct_info_get_value(PyGIBaseInfo *self, PyObject *args)
+{
+ PyObject *pybuffer;
+ PyBufferProcs *buffer_procs;
+ void *buffer;
+ char *field_name;
+ GArgument value;
+ GIFieldInfo *field_info;
+ int i;
+ int n_fields;
+ PyObject *retval;
+
+ if (!PyArg_ParseTuple(args, "Os:TypeInfo.getValue", &pybuffer, &field_name))
+ return NULL;
+
+ buffer_procs = pybuffer->ob_type->tp_as_buffer;
+ (*buffer_procs->bf_getreadbuffer)(pybuffer, 0, &buffer);
+
+ field_info = NULL;
+ n_fields = g_struct_info_get_n_fields ((GIStructInfo*) self->info);
+ for( i = 0; i < n_fields; i++ ) {
+ GIFieldInfo *temp = g_struct_info_get_field((GIStructInfo*) self->info, i);
+ if( !strcmp( g_base_info_get_name((GIBaseInfo *) temp), field_name ) ) {
+ field_info = temp;
+ break;
+ }
+ }
+
+ if( field_info == NULL ) {
+ return NULL;
+ }
+
+ if (!g_field_info_get_field (field_info, buffer, &value)) {
+ return NULL;
+ }
+
+ retval = pyg_argument_to_pyobject(&value, g_field_info_get_type (field_info));
+
+ Py_INCREF(retval);
+ return retval;
+}
+
+static PyObject *
+_wrap_g_struct_info_set_value(PyGIBaseInfo *self, PyObject *args)
+{
+ PyObject *pybuffer;
+ PyBufferProcs *buffer_procs;
+ void *buffer;
+ char *field_name;
+ GArgument arg;
+ GIFieldInfo *field_info;
+ int i;
+ int n_fields;
+ PyObject *value;
+
+ if (!PyArg_ParseTuple(args, "OsO:TypeInfo.setValue", &pybuffer, &field_name, &value))
+ return NULL;
+
+ buffer_procs = pybuffer->ob_type->tp_as_buffer;
+ (*buffer_procs->bf_getreadbuffer)(pybuffer, 0, &buffer);
+
+ field_info = NULL;
+ n_fields = g_struct_info_get_n_fields ((GIStructInfo*) self->info);
+ for( i = 0; i < n_fields; i++ ) {
+ GIFieldInfo *temp = g_struct_info_get_field((GIStructInfo*) self->info, i);
+ if( !strcmp( g_base_info_get_name((GIBaseInfo *) temp), field_name ) ) {
+ field_info = temp;
+ break;
+ }
+ }
+
+ if( field_info == NULL ) {
+ return NULL;
+ }
+
+ arg = pyg_argument_from_pyobject(value, g_field_info_get_type (field_info));
+
+ if (!g_field_info_set_field (field_info, buffer, &arg)) {
+ return NULL;
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
static PyMethodDef _PyGIStructInfo_methods[] = {
+ { "getFields", (PyCFunction)_wrap_g_struct_info_get_fields, METH_NOARGS },
{ "getMethods", (PyCFunction)_wrap_g_struct_info_get_methods, METH_NOARGS },
+ { "newBuffer", (PyCFunction)_wrap_g_struct_info_new_buffer, METH_NOARGS },
+ { "getValue", (PyCFunction)_wrap_g_struct_info_get_value, METH_VARARGS },
+ { "setValue", (PyCFunction)_wrap_g_struct_info_set_value, METH_VARARGS },
{ NULL, NULL, 0 }
};
diff --git a/bank/bank.h b/bank/bank.h
index b0c8ba6..b8f0181 100644
--- a/bank/bank.h
+++ b/bank/bank.h
@@ -73,7 +73,7 @@ extern PyTypeObject PyGIErrorDomainInfo_Type;
extern PyTypeObject PyGIUnresolvedInfo_Type;
GArgument pyg_argument_from_pyobject(PyObject *object,
- GIArgInfo *info);
+ GITypeInfo *info);
PyObject* pyg_argument_to_pyobject(GArgument *arg,
GITypeInfo *info);
diff --git a/bank/btypes.py b/bank/btypes.py
index 593bd0a..a72c93a 100644
--- a/bank/btypes.py
+++ b/bank/btypes.py
@@ -283,6 +283,27 @@ def buildInterface(info):
return newType
+class BaseBlob(object):
+ """Base class for Struct, Boxed and Union.
+ """
+ def __init__(self, buf=None):
+ if buf is None:
+ buf = self.__info__.newBuffer()
+ self.__dict__['__buffer__'] = buf
+
+ def __getattr__(self, name):
+ return self.__info__.getValue(self.__dict__['__buffer__'], name)
+
+ def __setattr__(self, name, value):
+ print "__setattr__ %r %r" % (name, value)
+ self.__info__.setValue(self.__dict__['__buffer__'], name, value)
+
+ def __eq__(self, other):
+ for field in self.__info__.getFields():
+ if getattr(self, field.getName()) != getattr(other, field.getName()):
+ return False
+ return True
+
def buildBoxed(info):
className = info.getName()
namespaceName = info.getNamespace()
@@ -294,7 +315,12 @@ def buildBoxed(info):
namespace = {}
namespace['__info__'] = info
namespace['__module__'] = namespaceName
- newType = type(className, (object,), namespace)
+
+ bases = (BaseBlob,)
+ if isinstance(info, repo.BoxedInfo):
+ bases += gobject.Boxed
+
+ newType = type(className, bases, namespace)
constructors = []
for method in info.getMethods():
@@ -310,18 +336,6 @@ def buildBoxed(info):
setupConstructors(className, newType, constructors)
- def __getattr__(self, name):
- pass
- newType.__getattr__ = new.instancemethod(__getattr__, None, newType)
-
- def __setattr__(self, name, value):
- pass
- newType.__setattr__ = new.instancemethod(__setattr__, None, newType)
-
- def __init__(self, buf):
- self.__dict__['__buffer__'] = buf
- newType.__init__ = new.instancemethod(__init__, None, newType)
-
_classDict[fullName] = newType
return newType
diff --git a/everything_unittest.py b/everything_unittest.py
index 7be9b55..5e39871 100644
--- a/everything_unittest.py
+++ b/everything_unittest.py
@@ -238,6 +238,12 @@ class TestGIEverything(unittest.TestCase):
a.some_int8 = 1
a.some_double = 4.15
a.some_enum= Everything.TestEnum.VALUE3
+
+ self.assertEquals(a.some_int, 3)
+ self.assertEquals(a.some_int8, 1)
+ self.assertEquals(a.some_double, 4.15)
+ self.assertEquals(a.some_enum, Everything.TestEnum.VALUE3)
+
return a
def testStructA(self):
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]