diff options
Diffstat (limited to 'gi/pygi-struct.c')
-rw-r--r-- | gi/pygi-struct.c | 177 |
1 files changed, 141 insertions, 36 deletions
diff --git a/gi/pygi-struct.c b/gi/pygi-struct.c index 29ea38e..f6e75e3 100644 --- a/gi/pygi-struct.c +++ b/gi/pygi-struct.c @@ -16,39 +16,80 @@ * 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-struct.h" +#include "pygi-foreign.h" +#include "pygi-info.h" +#include "pygi-type.h" +#include "pygi-type.h" +#include "pygpointer.h" +#include "pygi-util.h" -#include <pygobject.h> #include <girepository.h> -#include <pyglib-python-compat.h> + + +static GIBaseInfo * +struct_get_info (PyTypeObject *type) +{ + PyObject *py_info; + GIBaseInfo *info = NULL; + + py_info = PyObject_GetAttrString ((PyObject *)type, "__info__"); + if (py_info == NULL) { + return NULL; + } + if (!PyObject_TypeCheck (py_info, &PyGIStructInfo_Type) && + !PyObject_TypeCheck (py_info, &PyGIUnionInfo_Type)) { + PyErr_Format (PyExc_TypeError, "attribute '__info__' must be %s or %s, not %s", + PyGIStructInfo_Type.tp_name, + PyGIUnionInfo_Type.tp_name, + Py_TYPE(py_info)->tp_name); + goto out; + } + + info = ( (PyGIBaseInfo *) py_info)->info; + g_base_info_ref (info); + +out: + Py_DECREF (py_info); + + return info; +} static void -_struct_dealloc (PyGIStruct *self) +struct_dealloc (PyGIStruct *self) { - GIBaseInfo *info = _pygi_object_get_gi_info ( - (PyObject *) self, - &PyGIStructInfo_Type); + GIBaseInfo *info; + PyObject *error_type, *error_value, *error_traceback; + gboolean have_error = !!PyErr_Occurred (); + + if (have_error) + PyErr_Fetch (&error_type, &error_value, &error_traceback); + + info = struct_get_info (Py_TYPE (self)); if (info != NULL && g_struct_info_is_foreign ( (GIStructInfo *) info)) { - pygi_struct_foreign_release (info, ( (PyGPointer *) self)->pointer); + pygi_struct_foreign_release (info, pyg_pointer_get_ptr (self)); } else if (self->free_on_dealloc) { - g_free ( ( (PyGPointer *) self)->pointer); + g_free (pyg_pointer_get_ptr (self)); } - g_base_info_unref (info); + if (info != NULL) { + g_base_info_unref (info); + } + + if (have_error) + PyErr_Restore (error_type, error_value, error_traceback); - Py_TYPE( (PyGPointer *) self )->tp_free ( (PyObject *) self); + Py_TYPE (self)->tp_free ((PyObject *)self); } static PyObject * -_struct_new (PyTypeObject *type, - PyObject *args, - PyObject *kwargs) +struct_new (PyTypeObject *type, + PyObject *args, + PyObject *kwargs) { static char *kwlist[] = { NULL }; @@ -61,7 +102,7 @@ _struct_new (PyTypeObject *type, return NULL; } - info = _pygi_object_get_gi_info ( (PyObject *) type, &PyGIStructInfo_Type); + info = struct_get_info ( type ); if (info == NULL) { if (PyErr_ExceptionMatches (PyExc_AttributeError)) { PyErr_Format (PyExc_TypeError, "missing introspection information"); @@ -72,7 +113,7 @@ _struct_new (PyTypeObject *type, size = g_struct_info_get_size ( (GIStructInfo *) info); if (size == 0) { PyErr_Format (PyExc_TypeError, - "cannot allocate disguised struct %s.%s; consider adding a constructor to the library or to the overrides", + "struct cannot be created directly; try using a constructor, see: help(%s.%s)", g_base_info_get_namespace (info), g_base_info_get_name (info)); goto out; @@ -83,7 +124,7 @@ _struct_new (PyTypeObject *type, goto out; } - self = _pygi_struct_new (type, pointer, TRUE); + self = pygi_struct_new (type, pointer, TRUE); if (self == NULL) { g_free (pointer); } @@ -95,7 +136,7 @@ out: } static int -_struct_init (PyObject *self, +struct_init (PyObject *self, PyObject *args, PyObject *kwargs) { @@ -103,12 +144,44 @@ _struct_init (PyObject *self, return 0; } -PYGLIB_DEFINE_TYPE("gi.Struct", PyGIStruct_Type, PyGIStruct); +PYGI_DEFINE_TYPE("gi.Struct", PyGIStruct_Type, PyGIStruct); + PyObject * -_pygi_struct_new (PyTypeObject *type, - gpointer pointer, - gboolean free_on_dealloc) +pygi_struct_new_from_g_type (GType g_type, + gpointer pointer, + gboolean free_on_dealloc) +{ + PyGIStruct *self; + PyTypeObject *type; + + type = (PyTypeObject *)pygi_type_import_by_g_type (g_type); + + if (!type) + type = (PyTypeObject *)&PyGIStruct_Type; /* fallback */ + + if (!PyType_IsSubtype (type, &PyGIStruct_Type)) { + PyErr_SetString (PyExc_TypeError, "must be a subtype of gi.Struct"); + return NULL; + } + + self = (PyGIStruct *) type->tp_alloc (type, 0); + if (self == NULL) { + return NULL; + } + + pyg_pointer_set_ptr (self, pointer); + ( (PyGPointer *) self)->gtype = g_type; + self->free_on_dealloc = free_on_dealloc; + + return (PyObject *) self; +} + + +PyObject * +pygi_struct_new (PyTypeObject *type, + gpointer pointer, + gboolean free_on_dealloc) { PyGIStruct *self; GType g_type; @@ -125,25 +198,57 @@ _pygi_struct_new (PyTypeObject *type, g_type = pyg_type_from_object ( (PyObject *) type); + pyg_pointer_set_ptr (self, pointer); ( (PyGPointer *) self)->gtype = g_type; - ( (PyGPointer *) self)->pointer = pointer; self->free_on_dealloc = free_on_dealloc; return (PyObject *) self; } -void -_pygi_struct_register_types (PyObject *m) +static PyObject * +struct_repr(PyGIStruct *self) +{ + PyObject* repr; + GIBaseInfo *info; + PyGPointer *pointer = (PyGPointer *)self; + + info = struct_get_info (Py_TYPE (self)); + if (info == NULL) + return NULL; + + repr = PyUnicode_FromFormat ("<%s.%s object at %p (%s at %p)>", + g_base_info_get_namespace (info), + g_base_info_get_name (info), + self, g_type_name (pointer->gtype), + pointer->pointer); + + g_base_info_unref (info); + + return repr; +} + +/** + * Returns 0 on success, or -1 and sets an exception. + */ +int +pygi_struct_register_types (PyObject *m) { - Py_TYPE(&PyGIStruct_Type) = &PyType_Type; + Py_SET_TYPE(&PyGIStruct_Type, &PyType_Type); + g_assert (Py_TYPE (&PyGPointer_Type) != NULL); PyGIStruct_Type.tp_base = &PyGPointer_Type; - PyGIStruct_Type.tp_new = (newfunc) _struct_new; - PyGIStruct_Type.tp_init = (initproc) _struct_init; - PyGIStruct_Type.tp_dealloc = (destructor) _struct_dealloc; + PyGIStruct_Type.tp_new = (newfunc) struct_new; + PyGIStruct_Type.tp_init = (initproc) struct_init; + PyGIStruct_Type.tp_dealloc = (destructor) struct_dealloc; PyGIStruct_Type.tp_flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE); + PyGIStruct_Type.tp_repr = (reprfunc)struct_repr; + + if (PyType_Ready (&PyGIStruct_Type) < 0) + return -1; + Py_INCREF ((PyObject *) &PyGIStruct_Type); + if (PyModule_AddObject (m, "Struct", (PyObject *) &PyGIStruct_Type) < 0) { + Py_DECREF ((PyObject *) &PyGIStruct_Type); + return -1; + } - if (PyType_Ready (&PyGIStruct_Type)) - return; - if (PyModule_AddObject (m, "Struct", (PyObject *) &PyGIStruct_Type)) - return; + return 0; } |