Imported Upstream version 3.25.1
[platform/upstream/pygobject2.git] / gi / _gobject / pygpointer.c
1 /* -*- Mode: C; c-basic-offset: 4 -*-
2  * pygtk- Python bindings for the GTK toolkit.
3  * Copyright (C) 1998-2003  James Henstridge
4  *
5  *   pygpointer.c: wrapper for GPointer
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
20  * USA
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #  include <config.h>
25 #endif
26
27 #include <pyglib.h>
28 #include "pygobject-private.h"
29 #include "pygpointer.h"
30
31 #include "pygi.h"
32
33
34 GQuark pygpointer_class_key;
35
36 PYGLIB_DEFINE_TYPE("gobject.GPointer", PyGPointer_Type, PyGPointer);
37
38 static void
39 pyg_pointer_dealloc(PyGPointer *self)
40 {
41     Py_TYPE(self)->tp_free((PyObject *)self);
42 }
43
44 static PyObject*
45 pyg_pointer_richcompare(PyObject *self, PyObject *other, int op)
46 {
47     if (Py_TYPE(self) == Py_TYPE(other))
48         return _pyglib_generic_ptr_richcompare(((PyGPointer*)self)->pointer,
49                                                ((PyGPointer*)other)->pointer,
50                                                op);
51     else {
52         Py_INCREF(Py_NotImplemented);
53         return Py_NotImplemented;
54     }
55 }
56
57 static long
58 pyg_pointer_hash(PyGPointer *self)
59 {
60     return (long)self->pointer;
61 }
62
63 static PyObject *
64 pyg_pointer_repr(PyGPointer *self)
65 {
66     gchar buf[128];
67
68     g_snprintf(buf, sizeof(buf), "<%s at 0x%lx>", g_type_name(self->gtype),
69                (long)self->pointer);
70     return PYGLIB_PyUnicode_FromString(buf);
71 }
72
73 static int
74 pyg_pointer_init(PyGPointer *self, PyObject *args, PyObject *kwargs)
75 {
76     gchar buf[512];
77
78     if (!PyArg_ParseTuple(args, ":GPointer.__init__"))
79         return -1;
80
81     self->pointer = NULL;
82     self->gtype = 0;
83
84     g_snprintf(buf, sizeof(buf), "%s can not be constructed",
85                Py_TYPE(self)->tp_name);
86     PyErr_SetString(PyExc_NotImplementedError, buf);
87     return -1;
88 }
89
90 static void
91 pyg_pointer_free(PyObject *op)
92 {
93   PyObject_FREE(op);
94 }
95
96 /**
97  * pyg_register_pointer:
98  * @dict: the module dictionary to store the wrapper class.
99  * @class_name: the Python name for the wrapper class.
100  * @pointer_type: the GType of the pointer type being wrapped.
101  * @type: the wrapper class.
102  *
103  * Registers a wrapper for a pointer type.  The wrapper class will be
104  * a subclass of gobject.GPointer, and a reference to the wrapper
105  * class will be stored in the provided module dictionary.
106  */
107 void
108 pyg_register_pointer(PyObject *dict, const gchar *class_name,
109                      GType pointer_type, PyTypeObject *type)
110 {
111     PyObject *o;
112
113     g_return_if_fail(dict != NULL);
114     g_return_if_fail(class_name != NULL);
115     g_return_if_fail(pointer_type != 0);
116
117     if (!type->tp_dealloc) type->tp_dealloc = (destructor)pyg_pointer_dealloc;
118
119     Py_TYPE(type) = &PyType_Type;
120     type->tp_base = &PyGPointer_Type;
121
122     if (PyType_Ready(type) < 0) {
123         g_warning("could not get type `%s' ready", type->tp_name);
124         return;
125     }
126
127     PyDict_SetItemString(type->tp_dict, "__gtype__",
128                          o=pyg_type_wrapper_new(pointer_type));
129     Py_DECREF(o);
130
131     g_type_set_qdata(pointer_type, pygpointer_class_key, type);
132
133     PyDict_SetItemString(dict, (char *)class_name, (PyObject *)type);
134 }
135
136 /**
137  * pyg_pointer_new:
138  * @pointer_type: the GType of the pointer value.
139  * @pointer: the pointer value.
140  *
141  * Creates a wrapper for a pointer value.  Since G_TYPE_POINTER types
142  * don't register any information about how to copy/free them, there
143  * is no guarantee that the pointer will remain valid, and there is
144  * nothing registered to release the pointer when the pointer goes out
145  * of scope.  This is why we don't recommend people use these types.
146  *
147  * Returns: the boxed wrapper.
148  */
149 PyObject *
150 pyg_pointer_new(GType pointer_type, gpointer pointer)
151 {
152     PyGILState_STATE state;
153     PyGPointer *self;
154     PyTypeObject *tp;
155     g_return_val_if_fail(pointer_type != 0, NULL);
156
157     state = pyglib_gil_state_ensure();
158
159     if (!pointer) {
160         Py_INCREF(Py_None);
161         pyglib_gil_state_release(state);
162         return Py_None;
163     }
164
165     tp = g_type_get_qdata(pointer_type, pygpointer_class_key);
166
167     if (!tp)
168         tp = (PyTypeObject *)pygi_type_import_by_g_type(pointer_type);
169
170     if (!tp)
171         tp = (PyTypeObject *)&PyGPointer_Type; /* fallback */
172     self = PyObject_NEW(PyGPointer, tp);
173
174     pyglib_gil_state_release(state);
175
176     if (self == NULL)
177         return NULL;
178
179     self->pointer = pointer;
180     self->gtype = pointer_type;
181
182     return (PyObject *)self;
183 }
184
185 void
186 pygobject_pointer_register_types(PyObject *d)
187 {
188     pygpointer_class_key     = g_quark_from_static_string("PyGPointer::class");
189
190     PyGPointer_Type.tp_dealloc = (destructor)pyg_pointer_dealloc;
191     PyGPointer_Type.tp_richcompare = pyg_pointer_richcompare;
192     PyGPointer_Type.tp_repr = (reprfunc)pyg_pointer_repr;
193     PyGPointer_Type.tp_hash = (hashfunc)pyg_pointer_hash;
194     PyGPointer_Type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE;
195     PyGPointer_Type.tp_init = (initproc)pyg_pointer_init;
196     PyGPointer_Type.tp_free = (freefunc)pyg_pointer_free;
197     PYGOBJECT_REGISTER_GTYPE(d, PyGPointer_Type, "GPointer", G_TYPE_POINTER); 
198 }