summaryrefslogtreecommitdiff
path: root/gi
diff options
context:
space:
mode:
authorDongHun Kwak <dh0128.kwak@samsung.com>2017-07-12 08:37:54 +0900
committerDongHun Kwak <dh0128.kwak@samsung.com>2017-07-12 08:37:56 +0900
commit761a71bb8692ba42c26ed5ef872c4209b20bc470 (patch)
treec7000ef26526443e5140651ac7fb219617d2370e /gi
parent441a24af58aadb0ef05a7dd1dedc951b805c9c01 (diff)
downloadpygobject2-761a71bb8692ba42c26ed5ef872c4209b20bc470.tar.gz
pygobject2-761a71bb8692ba42c26ed5ef872c4209b20bc470.tar.bz2
pygobject2-761a71bb8692ba42c26ed5ef872c4209b20bc470.zip
Imported Upstream version 3.0.1
Change-Id: I26a0bcadb4a71ef2c031860ee9d617b250d3a6d7 Signed-off-by: DongHun Kwak <dh0128.kwak@samsung.com>
Diffstat (limited to 'gi')
-rw-r--r--gi/_gobject/gobjectmodule.c37
-rw-r--r--gi/_gobject/pygobject-private.h3
-rw-r--r--gi/_gobject/pygobject.c27
-rw-r--r--gi/_gobject/pygobject.h3
-rw-r--r--gi/pygi-marshal-from-py.c60
5 files changed, 109 insertions, 21 deletions
diff --git a/gi/_gobject/gobjectmodule.c b/gi/_gobject/gobjectmodule.c
index ffa323b..ac065a5 100644
--- a/gi/_gobject/gobjectmodule.c
+++ b/gi/_gobject/gobjectmodule.c
@@ -1048,7 +1048,7 @@ pygobject__g_instance_init(GTypeInstance *instance,
gpointer g_class)
{
GObject *object = (GObject *) instance;
- PyObject *wrapper;
+ PyObject *wrapper, *args, *kwargs;
wrapper = g_object_get_qdata(object, pygobject_wrapper_key);
if (wrapper == NULL) {
@@ -1059,6 +1059,27 @@ pygobject__g_instance_init(GTypeInstance *instance,
}
}
pygobject_init_wrapper_set(NULL);
+ if (wrapper == NULL) {
+ /* this looks like a python object created through
+ * g_object_new -> we have no python wrapper, so create it
+ * now */
+ PyGILState_STATE state;
+ state = pyglib_gil_state_ensure();
+ wrapper = pygobject_new_full(object, FALSE, g_class);
+
+ /* float the wrapper ref here because we are going to orphan it
+ * so we don't destroy the wrapper. The next call to pygobject_new_full
+ * will take the ref */
+ pygobject_ref_float (wrapper);
+ args = PyTuple_New(0);
+ kwargs = PyDict_New();
+ if (Py_TYPE(wrapper)->tp_init(wrapper, args, kwargs))
+ PyErr_Print();
+
+ Py_DECREF(args);
+ Py_DECREF(kwargs);
+ pyglib_gil_state_release(state);
+ }
}
@@ -1730,22 +1751,8 @@ pyg_object_new (PyGObject *self, PyObject *args, PyObject *kwargs)
g_type_class_unref(class);
if (obj) {
- PyObject *empty_args;
- PyObject *empty_kwargs;
- PyGILState_STATE state;
-
pygobject_sink (obj);
self = (PyGObject *) pygobject_new_full((GObject *)obj, FALSE, NULL);
- empty_args = PyTuple_New(0);
- empty_kwargs = PyDict_New();
-
- state = pyglib_gil_state_ensure();
- if (Py_TYPE(self)->tp_init((PyObject *)self, empty_args, empty_kwargs))
- PyErr_Print();
- pyglib_gil_state_release(state);
-
- Py_DECREF(empty_args);
- Py_DECREF(empty_kwargs);
g_object_unref(obj);
} else
self = NULL;
diff --git a/gi/_gobject/pygobject-private.h b/gi/_gobject/pygobject-private.h
index dabf0a4..1b1d6db 100644
--- a/gi/_gobject/pygobject-private.h
+++ b/gi/_gobject/pygobject-private.h
@@ -96,6 +96,9 @@ PyObject *pyg_integer_richcompare(PyObject *v,
gboolean pyg_gerror_exception_check(GError **error);
+void pygobject_ref_float(PyGObject *self);
+void pygobject_ref_sink(PyGObject *self);
+
/* from pygtype.h */
extern PyTypeObject PyGTypeWrapper_Type;
diff --git a/gi/_gobject/pygobject.c b/gi/_gobject/pygobject.c
index 48a9f18..0f0e5e2 100644
--- a/gi/_gobject/pygobject.c
+++ b/gi/_gobject/pygobject.c
@@ -560,6 +560,31 @@ pygobject_switch_to_toggle_ref(PyGObject *self)
g_object_unref(self->obj);
}
+/* Called when an custom gobject is initalized via g_object_new instead of
+ its constructor. The next time the wrapper is access via
+ pygobject_new_full it will sink the floating reference instead of
+ adding a new reference and causing a leak */
+
+void
+pygobject_ref_float(PyGObject *self)
+{
+ /* should only be floated once */
+ g_assert(!(self->private_flags.flags & PYGOBJECT_IS_FLOATING_REF));
+
+ self->private_flags.flags |= PYGOBJECT_IS_FLOATING_REF;
+}
+
+/* Called by gobject_new_full, if the floating flag is set remove it, otherwise
+ ref the pyobject */
+void
+pygobject_ref_sink(PyGObject *self)
+{
+ if (self->private_flags.flags & PYGOBJECT_IS_FLOATING_REF)
+ self->private_flags.flags &= ~PYGOBJECT_IS_FLOATING_REF;
+ else
+ Py_INCREF ( (PyObject *) self);
+}
+
/**
* pygobject_register_wrapper:
* @self: the wrapper instance
@@ -888,7 +913,7 @@ pygobject_new_full(GObject *obj, gboolean sink, gpointer g_class)
/* we already have a wrapper for this object -- return it. */
self = (PyGObject *)g_object_get_qdata(obj, pygobject_wrapper_key);
if (self != NULL) {
- Py_INCREF(self);
+ pygobject_ref_sink(self);
} else {
/* create wrapper */
PyGObjectData *inst_data = pyg_object_peek_inst_data(obj);
diff --git a/gi/_gobject/pygobject.h b/gi/_gobject/pygobject.h
index f728e15..8879fd0 100644
--- a/gi/_gobject/pygobject.h
+++ b/gi/_gobject/pygobject.h
@@ -23,7 +23,8 @@ struct _PyGClosure {
};
typedef enum {
- PYGOBJECT_USING_TOGGLE_REF = 1 << 0
+ PYGOBJECT_USING_TOGGLE_REF = 1 << 0,
+ PYGOBJECT_IS_FLOATING_REF = 1 << 1
} PyGObjectFlags;
/* closures is just an alias for what is found in the
diff --git a/gi/pygi-marshal-from-py.c b/gi/pygi-marshal-from-py.c
index fa74a22..b78cfe3 100644
--- a/gi/pygi-marshal-from-py.c
+++ b/gi/pygi-marshal-from-py.c
@@ -1416,10 +1416,62 @@ gboolean _pygi_marshal_from_py_interface_instance (PyGIInvokeState *state,
GType type = iface_cache->g_type;
if (!PyObject_IsInstance (py_arg, iface_cache->py_type)) {
- PyErr_Format (PyExc_TypeError, "Expected a %s, but got %s",
- iface_cache->type_name,
- py_arg->ob_type->tp_name);
- return FALSE;
+ /* wait, we might be a member of a union so manually check */
+ if (info_type == GI_INFO_TYPE_UNION) {
+ gint i;
+ gint n_fields;
+ gboolean is_member = FALSE;
+ GIUnionInfo *union_info = (GIUnionInfo *) iface_cache->interface_info;
+
+ n_fields = g_union_info_get_n_fields (union_info);
+
+ for (i = 0; i < n_fields; i++) {
+ GIFieldInfo *field_info;
+ GITypeInfo *field_type_info;
+
+ field_info = g_union_info_get_field (union_info, i);
+ field_type_info = g_field_info_get_type (field_info);
+
+ /* we can only check if the members are interfaces */
+ if (g_type_info_get_tag (field_type_info) ==
+ GI_TYPE_TAG_INTERFACE) {
+ PyObject *py_type;
+ GIInterfaceInfo *field_iface_info =
+ g_type_info_get_interface(field_type_info);
+
+ py_type = _pygi_type_import_by_gi_info (
+ (GIBaseInfo *) field_iface_info);
+
+ if (PyObject_IsInstance (py_arg, py_type)) {
+ is_member = TRUE;
+ break;
+ }
+
+ Py_XDECREF (py_type);
+ g_base_info_unref ( ( GIBaseInfo *) field_iface_info);
+
+ }
+
+ g_base_info_unref ( ( GIBaseInfo *) field_type_info);
+ g_base_info_unref ( ( GIBaseInfo *) field_info);
+
+ if (is_member)
+ break;
+ }
+
+ if (!is_member) {
+ PyErr_Format (PyExc_TypeError,
+ "Expected a %s, but got %s",
+ iface_cache->type_name,
+ py_arg->ob_type->tp_name);
+ return FALSE;
+ }
+ } else {
+ PyErr_Format (PyExc_TypeError, "Expected a %s, but got %s",
+ iface_cache->type_name,
+ py_arg->ob_type->tp_name);
+ return FALSE;
+ }
}
if (g_type_is_a (type, G_TYPE_BOXED)) {