Commit 8b70faa7 authored by Tomeu Vizoso's avatar Tomeu Vizoso
Browse files
parent e239faac
......@@ -132,6 +132,94 @@ _wrap_pyg_register_interface_info(PyObject *self, PyObject *args)
Py_RETURN_NONE;
}
static PyObject *
_wrap_pyg_hook_up_vfunc_implementation (PyObject *self, PyObject *args)
{
PyGIBaseInfo *py_info;
PyObject *py_type;
PyObject *py_function;
gpointer implementor_class = NULL;
GType ancestor_g_type = 0;
GType implementor_gtype = 0;
gpointer *method_ptr = NULL;
int length, i;
GIBaseInfo *vfunc_info;
GIBaseInfo *ancestor_info;
GIStructInfo *struct_info;
gboolean is_interface = FALSE;
PyGICClosure *closure = NULL;
if (!PyArg_ParseTuple(args, "O!O!O:hook_up_vfunc_implementation",
&PyGIBaseInfo_Type, &py_info,
&PyGTypeWrapper_Type, &py_type,
&py_function))
return NULL;
implementor_gtype = pyg_type_from_object(py_type);
g_assert(G_TYPE_IS_CLASSED(implementor_gtype));
vfunc_info = py_info->info;
ancestor_info = g_base_info_get_container(vfunc_info);
is_interface = g_base_info_get_type(ancestor_info) == GI_INFO_TYPE_INTERFACE;
ancestor_g_type = g_registered_type_info_get_g_type(
(GIRegisteredTypeInfo *)ancestor_info);
implementor_class = g_type_class_ref(implementor_gtype);
if (is_interface) {
GTypeInstance *implementor_iface_class;
implementor_iface_class = g_type_interface_peek(implementor_class,
ancestor_g_type);
g_type_class_unref (implementor_class);
implementor_class = implementor_iface_class;
struct_info = g_interface_info_get_iface_struct ((GIInterfaceInfo*)ancestor_info);
} else
struct_info = g_object_info_get_class_struct ((GIObjectInfo*)ancestor_info);
length = g_struct_info_get_n_fields(struct_info);
for (i = 0; i < length; i++) {
GIFieldInfo *field_info;
GITypeInfo *type_info;
GIBaseInfo *interface_info;
GICallbackInfo *callback_info;
gint offset;
field_info = g_struct_info_get_field (struct_info, i);
if (strcmp(g_base_info_get_name((GIBaseInfo*) field_info),
g_base_info_get_name((GIBaseInfo*) vfunc_info)) != 0)
continue;
type_info = g_field_info_get_type (field_info);
if (g_type_info_get_tag (type_info) != GI_TYPE_TAG_INTERFACE)
continue;
interface_info = g_type_info_get_interface (type_info);
g_assert(g_base_info_get_type(interface_info) == GI_INFO_TYPE_CALLBACK);
callback_info = (GICallbackInfo*) interface_info;
offset = g_field_info_get_offset(field_info);
method_ptr = G_STRUCT_MEMBER_P(implementor_class, offset);
closure = _pygi_make_native_closure((GICallableInfo*)callback_info,
GI_SCOPE_TYPE_NOTIFIED, py_function, NULL);
*method_ptr = closure->closure;
g_base_info_unref (interface_info);
g_base_info_unref (type_info);
g_base_info_unref (field_info);
break;
}
g_base_info_unref (struct_info);
g_type_class_unref (implementor_class);
Py_RETURN_NONE;
}
static PyMethodDef _pygi_functions[] = {
{ "enum_add", (PyCFunction)_wrap_pyg_enum_add, METH_VARARGS | METH_KEYWORDS },
......@@ -139,6 +227,7 @@ static PyMethodDef _pygi_functions[] = {
{ "set_object_has_new_constructor", (PyCFunction)_wrap_pyg_set_object_has_new_constructor, METH_VARARGS | METH_KEYWORDS },
{ "register_interface_info", (PyCFunction)_wrap_pyg_register_interface_info, METH_VARARGS },
{ "hook_up_vfunc_implementation", (PyCFunction)_wrap_pyg_hook_up_vfunc_implementation, METH_VARARGS },
{ NULL, NULL, 0 }
};
......
......@@ -1518,6 +1518,7 @@ _pygi_argument_to_object (GArgument *arg,
break;
}
case GI_INFO_TYPE_INTERFACE:
case GI_INFO_TYPE_OBJECT:
if (arg->v_pointer == NULL) {
object = Py_None;
......
......@@ -202,10 +202,9 @@ _pygi_create_callback (PyGIBaseInfo *function_info,
return FALSE;
}
/** Now actually build the closure **/
*closure_out = _pygi_make_native_closure((GICallableInfo *)callback_info,
callback_arg,
g_arg_info_get_scope(callback_arg),
py_function,
py_user_data);
......
......@@ -170,7 +170,7 @@ void _pygi_invoke_closure_free(gpointer data)
PyGICClosure*
_pygi_make_native_closure (GICallableInfo* info,
GIArgInfo* arg_info,
GIScopeType scope,
PyObject *py_function,
gpointer py_user_data)
{
......@@ -199,7 +199,7 @@ _pygi_make_native_closure (GICallableInfo* info,
/* Give the closure the information it needs to determine when
to free itself later */
closure->scope = g_arg_info_get_scope(arg_info);
closure->scope = scope;
return closure;
}
......@@ -48,7 +48,7 @@ void _pygi_closure_handle(ffi_cif *cif, void *result, void
void _pygi_invoke_closure_free(gpointer user_data);
PyGICClosure* _pygi_make_native_closure (GICallableInfo* info,
GIArgInfo* arg_info,
GIScopeType scope,
PyObject *function,
gpointer user_data);
......
......@@ -213,8 +213,8 @@ _pygi_info_new (GIBaseInfo *info)
PyErr_SetString(PyExc_NotImplementedError, "GISignalInfo bindings not implemented");
return NULL;
case GI_INFO_TYPE_VFUNC:
PyErr_SetString(PyExc_NotImplementedError, "GIVFuncInfo bindings not implemented");
return NULL;
type = &PyGIVFuncInfo_Type;
break;
case GI_INFO_TYPE_PROPERTY:
PyErr_SetString(PyExc_NotImplementedError, "GIPropertyInfo bindings not implemented");
return NULL;
......@@ -1709,12 +1709,49 @@ _wrap_g_object_info_get_constants (PyGIBaseInfo *self)
return infos;
}
static PyObject *
_wrap_g_object_info_get_vfuncs (PyGIBaseInfo *self)
{
gssize n_infos;
PyObject *infos;
gssize i;
n_infos = g_object_info_get_n_vfuncs((GIObjectInfo *)self->info);
infos = PyTuple_New(n_infos);
if (infos == NULL) {
return NULL;
}
for (i = 0; i < n_infos; i++) {
GIBaseInfo *info;
PyObject *py_info;
info = (GIBaseInfo *)g_object_info_get_vfunc((GIObjectInfo *)self->info, i);
g_assert(info != NULL);
py_info = _pygi_info_new(info);
g_base_info_unref(info);
if (py_info == NULL) {
Py_CLEAR(infos);
break;
}
PyTuple_SET_ITEM(infos, i, py_info);
}
return infos;
}
static PyMethodDef _PyGIObjectInfo_methods[] = {
{ "get_parent", (PyCFunction)_wrap_g_object_info_get_parent, METH_NOARGS },
{ "get_methods", (PyCFunction)_wrap_g_object_info_get_methods, METH_NOARGS },
{ "get_fields", (PyCFunction)_wrap_g_object_info_get_fields, METH_NOARGS },
{ "get_interfaces", (PyCFunction)_wrap_g_object_info_get_interfaces, METH_NOARGS },
{ "get_constants", (PyCFunction)_wrap_g_object_info_get_constants, METH_NOARGS },
{ "get_vfuncs", (PyCFunction)_wrap_g_object_info_get_vfuncs, METH_NOARGS },
{ NULL, NULL, 0 }
};
......@@ -1794,9 +1831,46 @@ _wrap_g_interface_info_get_constants (PyGIBaseInfo *self)
return infos;
}
static PyObject *
_wrap_g_interface_info_get_vfuncs (PyGIBaseInfo *self)
{
gssize n_infos;
PyObject *infos;
gssize i;
n_infos = g_interface_info_get_n_vfuncs((GIInterfaceInfo *)self->info);
infos = PyTuple_New(n_infos);
if (infos == NULL) {
return NULL;
}
for (i = 0; i < n_infos; i++) {
GIBaseInfo *info;
PyObject *py_info;
info = (GIBaseInfo *)g_interface_info_get_vfunc((GIInterfaceInfo *)self->info, i);
g_assert(info != NULL);
py_info = _pygi_info_new(info);
g_base_info_unref(info);
if (py_info == NULL) {
Py_CLEAR(infos);
break;
}
PyTuple_SET_ITEM(infos, i, py_info);
}
return infos;
}
static PyMethodDef _PyGIInterfaceInfo_methods[] = {
{ "get_methods", (PyCFunction)_wrap_g_interface_info_get_methods, METH_NOARGS },
{ "get_constants", (PyCFunction)_wrap_g_interface_info_get_constants, METH_NOARGS },
{ "get_vfuncs", (PyCFunction)_wrap_g_interface_info_get_vfuncs, METH_NOARGS },
{ NULL, NULL, 0 }
};
......@@ -2102,6 +2176,13 @@ static PyMethodDef _PyGIUnresolvedInfo_methods[] = {
{ NULL, NULL, 0 }
};
/* GIVFuncInfo */
_PyGI_DEFINE_INFO_TYPE("VFuncInfo", GIVFuncInfo, PyGIBaseInfo_Type);
static PyMethodDef _PyGIVFuncInfo_methods[] = {
{ NULL, NULL, 0 }
};
/* Private */
gchar *
......@@ -2151,6 +2232,7 @@ _pygi_info_register_types (PyObject *m)
_PyGI_REGISTER_TYPE(m, PyGIConstantInfo_Type, "ConstantInfo");
_PyGI_REGISTER_TYPE(m, PyGIValueInfo_Type, "ValueInfo");
_PyGI_REGISTER_TYPE(m, PyGIFieldInfo_Type, "FieldInfo");
_PyGI_REGISTER_TYPE(m, PyGIVFuncInfo_Type, "VFuncInfo");
#undef _PyGI_REGISTER_TYPE
}
......@@ -45,6 +45,7 @@ extern PyTypeObject PyGIConstantInfo_Type;
extern PyTypeObject PyGIValueInfo_Type;
extern PyTypeObject PyGIFieldInfo_Type;
extern PyTypeObject PyGIUnresolvedInfo_Type;
extern PyTypeObject PyGIVFuncInfo_Type;
#define PyGIBaseInfo_GET_GI_INFO(object) g_base_info_ref(((PyGIBaseInfo *)object)->info)
......
......@@ -30,7 +30,8 @@ from ._gi import \
ObjectInfo, \
StructInfo, \
set_object_has_new_constructor, \
register_interface_info
register_interface_info, \
hook_up_vfunc_implementation
def Function(info):
......@@ -91,6 +92,22 @@ class MetaClassHelper(object):
value = constant_info.get_value()
setattr(cls, name, value)
def _setup_vfuncs(cls):
for base in cls.__bases__:
if not hasattr(base, '__info__') or \
not hasattr(base.__info__, 'get_vfuncs'):
continue
for vfunc_info in base.__info__.get_vfuncs():
vfunc = getattr(cls, 'do_' + vfunc_info.get_name(), None)
if vfunc is None:
raise TypeError('Class implementing %s.%s should implement '
'the method do_%s()' % (base.__info__.get_namespace(),
base.__info__.get_name(),
vfunc_info.get_name()))
else:
hook_up_vfunc_implementation(vfunc_info, cls.__gtype__,
vfunc)
class GObjectMeta(gobject.GObjectMeta, MetaClassHelper):
......@@ -98,19 +115,18 @@ class GObjectMeta(gobject.GObjectMeta, MetaClassHelper):
super(GObjectMeta, cls).__init__(name, bases, dict_)
# Avoid touching anything else than the base class.
if cls.__info__.get_g_type().pytype is not None:
return
cls._setup_methods()
cls._setup_constants()
if isinstance(cls.__info__, ObjectInfo):
cls._setup_fields()
cls._setup_constructors()
set_object_has_new_constructor(cls.__info__.get_g_type())
elif isinstance(cls.__info__, InterfaceInfo):
register_interface_info(cls.__info__.get_g_type())
if cls.__info__.get_g_type().pytype is None:
cls._setup_methods()
cls._setup_constants()
if isinstance(cls.__info__, ObjectInfo):
cls._setup_fields()
cls._setup_constructors()
set_object_has_new_constructor(cls.__info__.get_g_type())
elif isinstance(cls.__info__, InterfaceInfo):
register_interface_info(cls.__info__.get_g_type())
else:
cls._setup_vfuncs()
class StructMeta(type, MetaClassHelper):
......
......@@ -1313,10 +1313,17 @@ class TestPythonGObject(unittest.TestCase):
class Object(GIMarshallingTests.Object):
__gtype_name__ = "Object"
def __init__(self, int):
GIMarshallingTests.Object.__init__(self)
self.val = None
def method(self):
# Don't call super, which asserts that self.int == 42.
pass
def do_method_int8_in(self, int8):
self.val = int8
def test_object(self):
self.assertTrue(issubclass(self.Object, GIMarshallingTests.Object))
......@@ -1326,6 +1333,11 @@ class TestPythonGObject(unittest.TestCase):
def test_object_method(self):
self.Object(int = 0).method()
def test_object_vfuncs(self):
object_ = self.Object(int = 42)
object_.method_int8_in(84)
self.assertEqual(object_.val, 84)
class TestMultiOutputArgs(unittest.TestCase):
......@@ -1351,12 +1363,18 @@ class TestInterfaces(unittest.TestCase):
__gtype_name__ = 'TestInterfaceImpl'
def __init__(self):
gobject.GObject.__init__(self)
self.val = None
def do_test_int8_in(self, int8):
self.val = int8
self.assertTrue(issubclass(TestInterfaceImpl, GIMarshallingTests.Interface))
instance = TestInterfaceImpl()
self.assertTrue(isinstance(instance, GIMarshallingTests.Interface))
GIMarshallingTests.test_interface_test_int8_in(instance, 42)
self.assertEquals(instance.val, 42)
class TestOverrides(unittest.TestCase):
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment