functions: revert the function init order to make pylint happy again. See #217
[pygobject.git] / gi / pygi-boxed.c
blob6a48159f3033eb907fb3cc1996f90e5778a106aa
1 /* -*- Mode: C; c-basic-offset: 4 -*-
2 * vim: tabstop=4 shiftwidth=4 expandtab
4 * Copyright (C) 2009 Simon van der Linden <svdlinden@src.gnome.org>
6 * pygi-boxed.c: wrapper to handle registered structures.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
22 #include "pygi-boxed.h"
23 #include "pygi-info.h"
24 #include "pygboxed.h"
25 #include "pygi-type.h"
26 #include "pygi-basictype.h"
27 #include "pygi-python-compat.h"
29 #include <girepository.h>
31 static void
32 boxed_dealloc (PyGIBoxed *self)
34 Py_TYPE (self)->tp_free ((PyObject *)self);
37 static PyObject *
38 boxed_del (PyGIBoxed *self)
40 GType g_type;
41 gpointer boxed = pyg_boxed_get_ptr (self);
43 if ( ( (PyGBoxed *) self)->free_on_dealloc && boxed != NULL) {
44 if (self->slice_allocated) {
45 g_slice_free1 (self->size, boxed);
46 self->slice_allocated = FALSE;
47 self->size = 0;
48 } else {
49 g_type = pyg_type_from_object ( (PyObject *) self);
50 g_boxed_free (g_type, boxed);
53 pyg_boxed_set_ptr (self, NULL);
55 Py_RETURN_NONE;
58 void *
59 pygi_boxed_alloc (GIBaseInfo *info, gsize *size_out)
61 gpointer boxed = NULL;
62 gsize size = 0;
64 switch (g_base_info_get_type (info)) {
65 case GI_INFO_TYPE_UNION:
66 size = g_union_info_get_size ( (GIUnionInfo *) info);
67 break;
68 case GI_INFO_TYPE_BOXED:
69 case GI_INFO_TYPE_STRUCT:
70 size = g_struct_info_get_size ( (GIStructInfo *) info);
71 break;
72 default:
73 PyErr_Format (PyExc_TypeError,
74 "info should be Boxed or Union, not '%d'",
75 g_base_info_get_type (info));
76 return NULL;
79 if (size == 0) {
80 PyErr_Format (PyExc_TypeError,
81 "boxed cannot be created directly; try using a constructor, see: help(%s.%s)",
82 g_base_info_get_namespace (info),
83 g_base_info_get_name (info));
84 return NULL;
87 if( size_out != NULL)
88 *size_out = size;
90 boxed = g_slice_alloc0 (size);
91 if (boxed == NULL)
92 PyErr_NoMemory();
93 return boxed;
96 static PyObject *
97 boxed_new (PyTypeObject *type,
98 PyObject *args,
99 PyObject *kwargs)
101 GIBaseInfo *info;
102 gsize size = 0;
103 gpointer boxed;
104 PyGIBoxed *self = NULL;
106 info = _pygi_object_get_gi_info ( (PyObject *) type, &PyGIBaseInfo_Type);
107 if (info == NULL) {
108 if (PyErr_ExceptionMatches (PyExc_AttributeError)) {
109 PyErr_Format (PyExc_TypeError, "missing introspection information");
111 return NULL;
114 boxed = pygi_boxed_alloc (info, &size);
115 if (boxed == NULL) {
116 goto out;
119 self = (PyGIBoxed *) pygi_boxed_new (type, boxed, TRUE, size);
120 if (self == NULL) {
121 g_slice_free1 (size, boxed);
122 goto out;
125 self->size = size;
126 self->slice_allocated = TRUE;
128 out:
129 g_base_info_unref (info);
131 return (PyObject *) self;
134 static int
135 boxed_init (PyObject *self,
136 PyObject *args,
137 PyObject *kwargs)
139 static char *kwlist[] = { NULL };
141 if (!PyArg_ParseTupleAndKeywords (args, kwargs, "", kwlist)) {
142 PyErr_Clear ();
143 PyErr_Warn (PyExc_DeprecationWarning,
144 "Passing arguments to gi.types.Boxed.__init__() is deprecated. "
145 "All arguments passed will be ignored.");
148 /* Don't call PyGBoxed's init, which raises an exception. */
149 return 0;
152 PYGLIB_DEFINE_TYPE("gi.Boxed", PyGIBoxed_Type, PyGIBoxed);
154 PyObject *
155 pygi_boxed_new (PyTypeObject *type,
156 gpointer boxed,
157 gboolean free_on_dealloc,
158 gsize allocated_slice)
160 PyGIBoxed *self;
162 if (!boxed) {
163 Py_RETURN_NONE;
166 if (!PyType_IsSubtype (type, &PyGIBoxed_Type)) {
167 PyErr_SetString (PyExc_TypeError, "must be a subtype of gi.Boxed");
168 return NULL;
171 self = (PyGIBoxed *) type->tp_alloc (type, 0);
172 if (self == NULL) {
173 return NULL;
176 ( (PyGBoxed *) self)->gtype = pyg_type_from_object ( (PyObject *) type);
177 ( (PyGBoxed *) self)->free_on_dealloc = free_on_dealloc;
178 pyg_boxed_set_ptr (self, boxed);
179 if (allocated_slice > 0) {
180 self->size = allocated_slice;
181 self->slice_allocated = TRUE;
182 } else {
183 self->size = 0;
184 self->slice_allocated = FALSE;
187 return (PyObject *) self;
190 static PyObject *
191 boxed_get_free_on_dealloc(PyGIBoxed *self, void *closure)
193 return pygi_gboolean_to_py( ((PyGBoxed *)self)->free_on_dealloc );
196 static PyObject *
197 boxed_get_is_valid (PyGIBoxed *self, void *closure)
199 return pygi_gboolean_to_py (pyg_boxed_get_ptr (self) != NULL);
203 * pygi_boxed_copy_in_place:
205 * Replace the boxed pointer held by this wrapper with a boxed copy
206 * freeing the previously held pointer (when free_on_dealloc is TRUE).
207 * This can be used in cases where Python is passed a reference which
208 * it does not own and the wrapper is held by the Python program
209 * longer than the duration of a callback it was passed to.
211 void
212 pygi_boxed_copy_in_place (PyGIBoxed *self)
214 PyGBoxed *pygboxed = (PyGBoxed *)self;
215 gpointer ptr = pyg_boxed_get_ptr (self);
216 gpointer copy = NULL;
218 if (ptr)
219 copy = g_boxed_copy (pygboxed->gtype, ptr);
221 boxed_del (self);
222 pyg_boxed_set_ptr (pygboxed, copy);
223 pygboxed->free_on_dealloc = TRUE;
226 static PyGetSetDef pygi_boxed_getsets[] = {
227 { "_free_on_dealloc", (getter)boxed_get_free_on_dealloc, (setter)0 },
228 { "_is_valid", (getter)boxed_get_is_valid, (setter)0 },
229 { NULL, 0, 0 }
232 static PyMethodDef boxed_methods[] = {
233 { "__del__", (PyCFunction)boxed_del, METH_NOARGS },
234 { NULL, NULL, 0 }
238 * Returns 0 on success, or -1 and sets an exception.
241 pygi_boxed_register_types (PyObject *m)
243 Py_TYPE(&PyGIBoxed_Type) = &PyType_Type;
244 g_assert (Py_TYPE (&PyGBoxed_Type) != NULL);
245 PyGIBoxed_Type.tp_base = &PyGBoxed_Type;
246 PyGIBoxed_Type.tp_new = (newfunc) boxed_new;
247 PyGIBoxed_Type.tp_init = (initproc) boxed_init;
248 PyGIBoxed_Type.tp_dealloc = (destructor) boxed_dealloc;
249 PyGIBoxed_Type.tp_flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE);
250 PyGIBoxed_Type.tp_getset = pygi_boxed_getsets;
251 PyGIBoxed_Type.tp_methods = boxed_methods;
253 if (PyType_Ready (&PyGIBoxed_Type) < 0)
254 return -1;
255 Py_INCREF ((PyObject *) &PyGIBoxed_Type);
256 if (PyModule_AddObject (m, "Boxed", (PyObject *) &PyGIBoxed_Type) < 0) {
257 Py_DECREF ((PyObject *) &PyGIBoxed_Type);
258 return -1;
261 return 0;