summaryrefslogtreecommitdiff
path: root/gi/pygi-boxed.c
diff options
context:
space:
mode:
Diffstat (limited to 'gi/pygi-boxed.c')
-rw-r--r--gi/pygi-boxed.c168
1 files changed, 118 insertions, 50 deletions
diff --git a/gi/pygi-boxed.c b/gi/pygi-boxed.c
index 5bf2c19..9deb62a 100644
--- a/gi/pygi-boxed.c
+++ b/gi/pygi-boxed.c
@@ -16,38 +16,66 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
- * USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
-#include "pygi-private.h"
+#include "pygi-boxed.h"
+#include "pygi-info.h"
+#include "pygboxed.h"
+#include "pygi-type.h"
+#include "pygi-basictype.h"
+#include "pygi-util.h"
-#include <pygobject.h>
#include <girepository.h>
-#include <pyglib-python-compat.h>
+
+struct _PyGIBoxed {
+ PyGBoxed base;
+ gboolean slice_allocated;
+ gsize size;
+};
static void
-_boxed_dealloc (PyGIBoxed *self)
+boxed_clear (PyGIBoxed *self)
{
- GType g_type;
+ gpointer boxed = pyg_boxed_get_ptr (self);
+ GType g_type = ((PyGBoxed *)self)->gtype;
- if ( ( (PyGBoxed *) self)->free_on_dealloc) {
+ if ( ( (PyGBoxed *) self)->free_on_dealloc && boxed != NULL) {
if (self->slice_allocated) {
- g_slice_free1 (self->size, ( (PyGBoxed *) self)->boxed);
+ if (g_type && g_type_is_a (g_type, G_TYPE_VALUE))
+ g_value_unset (boxed);
+ g_slice_free1 (self->size, boxed);
+ self->slice_allocated = FALSE;
+ self->size = 0;
} else {
- g_type = pyg_type_from_object ( (PyObject *) self);
- g_boxed_free (g_type, ( (PyGBoxed *) self)->boxed);
+ g_boxed_free (g_type, boxed);
}
}
+ pyg_boxed_set_ptr (self, NULL);
+}
- Py_TYPE( (PyGObject *) self)->tp_free ( (PyObject *) self);
+static PyObject *
+boxed_clear_wrapper (PyGIBoxed *self)
+{
+ boxed_clear (self);
+
+ Py_RETURN_NONE;
+}
+
+
+static void
+boxed_dealloc (PyGIBoxed *self)
+{
+ boxed_clear (self);
+
+ Py_TYPE (self)->tp_free ((PyObject *)self);
}
void *
-_pygi_boxed_alloc (GIBaseInfo *info, gsize *size_out)
+pygi_boxed_alloc (GIBaseInfo *info, gsize *size_out)
{
- gsize size;
+ gpointer boxed = NULL;
+ gsize size = 0;
switch (g_base_info_get_type (info)) {
case GI_INFO_TYPE_UNION:
@@ -64,28 +92,33 @@ _pygi_boxed_alloc (GIBaseInfo *info, gsize *size_out)
return NULL;
}
+ if (size == 0) {
+ PyErr_Format (PyExc_TypeError,
+ "boxed cannot be created directly; try using a constructor, see: help(%s.%s)",
+ g_base_info_get_namespace (info),
+ g_base_info_get_name (info));
+ return NULL;
+ }
+
if( size_out != NULL)
*size_out = size;
- return g_slice_alloc0 (size);
+ boxed = g_slice_alloc0 (size);
+ if (boxed == NULL)
+ PyErr_NoMemory();
+ return boxed;
}
static PyObject *
-_boxed_new (PyTypeObject *type,
+boxed_new (PyTypeObject *type,
PyObject *args,
PyObject *kwargs)
{
- static char *kwlist[] = { NULL };
-
GIBaseInfo *info;
gsize size = 0;
gpointer boxed;
PyGIBoxed *self = NULL;
- if (!PyArg_ParseTupleAndKeywords (args, kwargs, "", kwlist)) {
- return NULL;
- }
-
info = _pygi_object_get_gi_info ( (PyObject *) type, &PyGIBaseInfo_Type);
if (info == NULL) {
if (PyErr_ExceptionMatches (PyExc_AttributeError)) {
@@ -94,13 +127,12 @@ _boxed_new (PyTypeObject *type,
return NULL;
}
- boxed = _pygi_boxed_alloc (info, &size);
+ boxed = pygi_boxed_alloc (info, &size);
if (boxed == NULL) {
- PyErr_NoMemory();
goto out;
}
- self = (PyGIBoxed *) _pygi_boxed_new (type, boxed, TRUE, size);
+ self = (PyGIBoxed *) pygi_boxed_new (type, boxed, TRUE, size);
if (self == NULL) {
g_slice_free1 (size, boxed);
goto out;
@@ -116,21 +148,30 @@ out:
}
static int
-_boxed_init (PyObject *self,
+boxed_init (PyObject *self,
PyObject *args,
PyObject *kwargs)
{
+ static char *kwlist[] = { NULL };
+
+ if (!PyArg_ParseTupleAndKeywords (args, kwargs, "", kwlist)) {
+ PyErr_Clear ();
+ PyErr_Warn (PyExc_DeprecationWarning,
+ "Passing arguments to gi.types.Boxed.__init__() is deprecated. "
+ "All arguments passed will be ignored.");
+ }
+
/* Don't call PyGBoxed's init, which raises an exception. */
return 0;
}
-PYGLIB_DEFINE_TYPE("gi.Boxed", PyGIBoxed_Type, PyGIBoxed);
+PYGI_DEFINE_TYPE("gi.Boxed", PyGIBoxed_Type, PyGIBoxed);
PyObject *
-_pygi_boxed_new (PyTypeObject *type,
- gpointer boxed,
- gboolean free_on_dealloc,
- gsize allocated_slice)
+pygi_boxed_new (PyTypeObject *type,
+ gpointer boxed,
+ gboolean free_on_dealloc,
+ gsize allocated_slice)
{
PyGIBoxed *self;
@@ -149,8 +190,8 @@ _pygi_boxed_new (PyTypeObject *type,
}
( (PyGBoxed *) self)->gtype = pyg_type_from_object ( (PyObject *) type);
- ( (PyGBoxed *) self)->boxed = boxed;
( (PyGBoxed *) self)->free_on_dealloc = free_on_dealloc;
+ pyg_boxed_set_ptr (self, boxed);
if (allocated_slice > 0) {
self->size = allocated_slice;
self->slice_allocated = TRUE;
@@ -162,30 +203,57 @@ _pygi_boxed_new (PyTypeObject *type,
return (PyObject *) self;
}
-static PyObject *
-_pygi_boxed_get_free_on_dealloc(PyGIBoxed *self, void *closure)
+/**
+ * pygi_boxed_copy_in_place:
+ *
+ * Replace the boxed pointer held by this wrapper with a boxed copy
+ * freeing the previously held pointer (when free_on_dealloc is TRUE).
+ * This can be used in cases where Python is passed a reference which
+ * it does not own and the wrapper is held by the Python program
+ * longer than the duration of a callback it was passed to.
+ */
+void
+pygi_boxed_copy_in_place (PyGIBoxed *self)
{
- return PyBool_FromLong( ((PyGBoxed *)self)->free_on_dealloc );
+ PyGBoxed *pygboxed = (PyGBoxed *)self;
+ gpointer ptr = pyg_boxed_get_ptr (self);
+ gpointer copy = NULL;
+
+ if (ptr)
+ copy = g_boxed_copy (pygboxed->gtype, ptr);
+
+ boxed_clear (self);
+ pyg_boxed_set_ptr (pygboxed, copy);
+ pygboxed->free_on_dealloc = TRUE;
}
-static PyGetSetDef pygi_boxed_getsets[] = {
- { "_free_on_dealloc", (getter)_pygi_boxed_get_free_on_dealloc, (setter)0 },
- { NULL, 0, 0 }
+static PyMethodDef boxed_methods[] = {
+ { "_clear_boxed", (PyCFunction)boxed_clear_wrapper, METH_NOARGS },
+ { NULL, NULL, 0 }
};
-void
-_pygi_boxed_register_types (PyObject *m)
+/**
+ * Returns 0 on success, or -1 and sets an exception.
+ */
+int
+pygi_boxed_register_types (PyObject *m)
{
- Py_TYPE(&PyGIBoxed_Type) = &PyType_Type;
+ Py_SET_TYPE(&PyGIBoxed_Type, &PyType_Type);
+ g_assert (Py_TYPE (&PyGBoxed_Type) != NULL);
PyGIBoxed_Type.tp_base = &PyGBoxed_Type;
- PyGIBoxed_Type.tp_new = (newfunc) _boxed_new;
- PyGIBoxed_Type.tp_init = (initproc) _boxed_init;
- PyGIBoxed_Type.tp_dealloc = (destructor) _boxed_dealloc;
+ PyGIBoxed_Type.tp_new = (newfunc) boxed_new;
+ PyGIBoxed_Type.tp_init = (initproc) boxed_init;
+ PyGIBoxed_Type.tp_dealloc = (destructor) boxed_dealloc;
PyGIBoxed_Type.tp_flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE);
- PyGIBoxed_Type.tp_getset = pygi_boxed_getsets;
+ PyGIBoxed_Type.tp_methods = boxed_methods;
- if (PyType_Ready (&PyGIBoxed_Type))
- return;
- if (PyModule_AddObject (m, "Boxed", (PyObject *) &PyGIBoxed_Type))
- return;
+ if (PyType_Ready (&PyGIBoxed_Type) < 0)
+ return -1;
+ Py_INCREF ((PyObject *) &PyGIBoxed_Type);
+ if (PyModule_AddObject (m, "Boxed", (PyObject *) &PyGIBoxed_Type) < 0) {
+ Py_DECREF ((PyObject *) &PyGIBoxed_Type);
+ return -1;
+ }
+
+ return 0;
}