873a56eb7bcf94d14e14f7dd2badc15bcc044955
[platform/upstream/pygobject2.git] / gi / gimodule.c
1 /* -*- Mode: C; c-basic-offset: 4 -*-
2  * vim: tabstop=4 shiftwidth=4 expandtab
3  *
4  * Copyright (C) 2005-2009 Johan Dahlin <johan@gnome.org>
5  *
6  *   gimodule.c: wrapper for the gobject-introspection library.
7  *
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.
12  *
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.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
21  * USA
22  */
23
24 #include "pygi-private.h"
25 #include "pygi.h"
26
27 #include <pygobject.h>
28 #include <pyglib-python-compat.h>
29
30 static PyObject *
31 _wrap_pyg_enum_add (PyObject *self,
32                     PyObject *args,
33                     PyObject *kwargs)
34 {
35     static char *kwlist[] = { "g_type", NULL };
36     PyObject *py_g_type;
37     GType g_type;
38
39     if (!PyArg_ParseTupleAndKeywords (args, kwargs,
40                                       "O!:enum_add",
41                                       kwlist, &PyGTypeWrapper_Type, &py_g_type)) {
42         return NULL;
43     }
44
45     g_type = pyg_type_from_object (py_g_type);
46     if (g_type == G_TYPE_INVALID) {
47         return NULL;
48     }
49
50     return pyg_enum_add (NULL, g_type_name (g_type), NULL, g_type);
51 }
52
53 static PyObject *
54 _wrap_pyg_enum_register_new_gtype_and_add (PyObject *self,
55                                            PyObject *args,
56                                            PyObject *kwargs)
57 {
58     static char *kwlist[] = { "info", NULL };
59     PyGIBaseInfo *py_info;
60     GIEnumInfo *info;
61     gint n_values;
62     GEnumValue *g_enum_values;
63     GType g_type;
64     const gchar *type_name;
65
66     if (!PyArg_ParseTupleAndKeywords (args, kwargs,
67                                       "O:enum_add_make_new_gtype",
68                                       kwlist, (PyObject *)&py_info)) {
69         return NULL;
70     }
71
72     if (!GI_IS_ENUM_INFO (py_info->info) ||
73             g_base_info_get_type ((GIBaseInfo *) py_info->info) != GI_INFO_TYPE_ENUM) {
74         PyErr_SetString (PyExc_TypeError, "info must be an EnumInfo with info type GI_INFO_TYPE_ENUM");
75         return NULL;
76     }
77
78     info = (GIEnumInfo *)py_info->info;
79     n_values = g_enum_info_get_n_values (info);
80     g_enum_values = g_new0 (GEnumValue, n_values + 1);
81
82     for (int i=0; i < n_values; i++) {
83         GIValueInfo *value_info;
84         GEnumValue *enum_value;
85         const gchar *name;
86         const gchar *c_identifier;
87
88         value_info = g_enum_info_get_value (info, i);
89         name = g_base_info_get_name ((GIBaseInfo *) value_info);
90         c_identifier = g_base_info_get_attribute ((GIBaseInfo *) value_info,
91                                                   "c:identifier");
92
93         enum_value = &g_enum_values[i];
94         enum_value->value_nick = g_strdup (name);
95         enum_value->value = g_value_info_get_value (value_info);
96
97         if (c_identifier == NULL) {
98             enum_value->value_name = enum_value->value_nick;
99         } else {
100             enum_value->value_name = g_strdup (c_identifier);
101         }
102
103         g_base_info_unref ((GIBaseInfo *) value_info);
104     }
105
106     g_enum_values[n_values].value = 0;
107     g_enum_values[n_values].value_nick = NULL;
108     g_enum_values[n_values].value_name = NULL;
109
110     type_name = g_base_info_get_name ((GIBaseInfo *) info);
111     type_name = g_strdup (type_name);
112     g_type = g_enum_register_static (type_name, g_enum_values);
113
114     return pyg_enum_add (NULL, g_type_name (g_type), NULL, g_type);
115 }
116
117 static PyObject *
118 _wrap_pyg_flags_add (PyObject *self,
119                      PyObject *args,
120                      PyObject *kwargs)
121 {
122     static char *kwlist[] = { "g_type", NULL };
123     PyObject *py_g_type;
124     GType g_type;
125
126     if (!PyArg_ParseTupleAndKeywords (args, kwargs,
127                                       "O!:flags_add",
128                                       kwlist, &PyGTypeWrapper_Type, &py_g_type)) {
129         return NULL;
130     }
131
132     g_type = pyg_type_from_object (py_g_type);
133     if (g_type == G_TYPE_INVALID) {
134         return NULL;
135     }
136
137     return pyg_flags_add (NULL, g_type_name (g_type), NULL, g_type);
138 }
139
140 static PyObject *
141 _wrap_pyg_flags_register_new_gtype_and_add (PyObject *self,
142                                             PyObject *args,
143                                             PyObject *kwargs)
144 {
145     static char *kwlist[] = { "info", NULL };
146     PyGIBaseInfo *py_info;
147     GIEnumInfo *info;
148     gint n_values;
149     GFlagsValue *g_flags_values;
150     GType g_type;
151     const gchar *type_name;
152
153     if (!PyArg_ParseTupleAndKeywords (args, kwargs,
154                                       "O:flags_add_make_new_gtype",
155                                       kwlist, (PyObject *)&py_info)) {
156         return NULL;
157     }
158
159     if (!GI_IS_ENUM_INFO (py_info->info) ||
160             g_base_info_get_type ((GIBaseInfo *) py_info->info) != GI_INFO_TYPE_FLAGS) {
161         PyErr_SetString (PyExc_TypeError, "info must be an EnumInfo with info type GI_INFO_TYPE_FLAGS");
162         return NULL;
163     }
164
165     info = (GIEnumInfo *)py_info->info;
166     n_values = g_enum_info_get_n_values (info);
167     g_flags_values = g_new0 (GFlagsValue, n_values + 1);
168
169     for (int i=0; i < n_values; i++) {
170         GIValueInfo *value_info;
171         GFlagsValue *flags_value;
172         const gchar *name;
173         const gchar *c_identifier;
174
175         value_info = g_enum_info_get_value (info, i);
176         name = g_base_info_get_name ((GIBaseInfo *) value_info);
177         c_identifier = g_base_info_get_attribute ((GIBaseInfo *) value_info,
178                                                   "c:identifier");
179
180         flags_value = &g_flags_values[i];
181         flags_value->value_nick = g_strdup (name);
182         flags_value->value = g_value_info_get_value (value_info);
183
184         if (c_identifier == NULL) {
185             flags_value->value_name = flags_value->value_nick;
186         } else {
187             flags_value->value_name = g_strdup (c_identifier);
188         }
189
190         g_base_info_unref ((GIBaseInfo *) value_info);
191     }
192
193     g_flags_values[n_values].value = 0;
194     g_flags_values[n_values].value_nick = NULL;
195     g_flags_values[n_values].value_name = NULL;
196
197     type_name = g_base_info_get_name ((GIBaseInfo *) info);
198     type_name = g_strdup (type_name);
199     g_type = g_flags_register_static (type_name, g_flags_values);
200
201     return pyg_flags_add (NULL, g_type_name (g_type), NULL, g_type);
202 }
203
204 static void
205 initialize_interface (GTypeInterface *iface, PyTypeObject *pytype)
206 {
207     // pygobject prints a warning if interface_init is NULL
208 }
209
210 static PyObject *
211 _wrap_pyg_register_interface_info (PyObject *self, PyObject *args)
212 {
213     PyObject *py_g_type;
214     GType g_type;
215     GInterfaceInfo *info;
216
217     if (!PyArg_ParseTuple (args, "O!:register_interface_info",
218                            &PyGTypeWrapper_Type, &py_g_type)) {
219         return NULL;
220     }
221
222     g_type = pyg_type_from_object (py_g_type);
223     if (!g_type_is_a (g_type, G_TYPE_INTERFACE)) {
224         PyErr_SetString (PyExc_TypeError, "must be an interface");
225         return NULL;
226     }
227
228     info = g_new0 (GInterfaceInfo, 1);
229     info->interface_init = (GInterfaceInitFunc) initialize_interface;
230
231     pyg_register_interface_info (g_type, info);
232
233     Py_RETURN_NONE;
234 }
235
236 static void
237 find_vfunc_info (GIBaseInfo *vfunc_info,
238                  GType implementor_gtype,
239                  gpointer *implementor_class_ret,
240                  gpointer *implementor_vtable_ret,
241                  GIFieldInfo **field_info_ret)
242 {
243     GType ancestor_g_type = 0;
244     int length, i;
245     GIBaseInfo *ancestor_info;
246     GIStructInfo *struct_info;
247     gpointer implementor_class = NULL;
248     gboolean is_interface = FALSE;
249
250     ancestor_info = g_base_info_get_container (vfunc_info);
251     is_interface = g_base_info_get_type (ancestor_info) == GI_INFO_TYPE_INTERFACE;
252
253     ancestor_g_type = g_registered_type_info_get_g_type (
254                           (GIRegisteredTypeInfo *) ancestor_info);
255     implementor_class = g_type_class_ref (implementor_gtype);
256     if (is_interface) {
257         GTypeInstance *implementor_iface_class;
258         implementor_iface_class = g_type_interface_peek (implementor_class,
259                                                          ancestor_g_type);
260         if (implementor_iface_class == NULL) {
261             g_type_class_unref (implementor_class);
262             PyErr_Format (PyExc_RuntimeError,
263                           "Couldn't find GType of implementor of interface %s. "
264                           "Forgot to set __gtype_name__?",
265                           g_type_name (ancestor_g_type));
266             return;
267         }
268
269         *implementor_vtable_ret = implementor_iface_class;
270
271         struct_info = g_interface_info_get_iface_struct ( (GIInterfaceInfo*) ancestor_info);
272     } else {
273         struct_info = g_object_info_get_class_struct ( (GIObjectInfo*) ancestor_info);
274         *implementor_vtable_ret = implementor_class;
275     }
276
277     *implementor_class_ret = implementor_class;
278
279     length = g_struct_info_get_n_fields (struct_info);
280     for (i = 0; i < length; i++) {
281         GIFieldInfo *field_info;
282         GITypeInfo *type_info;
283
284         field_info = g_struct_info_get_field (struct_info, i);
285
286         if (strcmp (g_base_info_get_name ( (GIBaseInfo*) field_info),
287                     g_base_info_get_name ( (GIBaseInfo*) vfunc_info)) != 0) {
288             g_base_info_unref (field_info);
289             continue;
290         }
291
292         type_info = g_field_info_get_type (field_info);
293         if (g_type_info_get_tag (type_info) == GI_TYPE_TAG_INTERFACE) {
294             g_base_info_unref (type_info);
295             *field_info_ret = field_info;
296             break;
297         }
298
299         g_base_info_unref (type_info);
300         g_base_info_unref (field_info);
301     }
302
303     g_base_info_unref (struct_info);
304 }
305
306 static PyObject *
307 _wrap_pyg_hook_up_vfunc_implementation (PyObject *self, PyObject *args)
308 {
309     PyGIBaseInfo *py_info;
310     PyObject *py_type;
311     PyObject *py_function;
312     GType implementor_gtype = 0;
313     gpointer implementor_class = NULL;
314     gpointer implementor_vtable = NULL;
315     GIFieldInfo *field_info = NULL;
316     gpointer *method_ptr = NULL;
317     PyGICClosure *closure = NULL;
318
319     if (!PyArg_ParseTuple (args, "O!O!O:hook_up_vfunc_implementation",
320                            &PyGIBaseInfo_Type, &py_info,
321                            &PyGTypeWrapper_Type, &py_type,
322                            &py_function))
323         return NULL;
324
325     implementor_gtype = pyg_type_from_object (py_type);
326     g_assert (G_TYPE_IS_CLASSED (implementor_gtype));
327
328     find_vfunc_info (py_info->info, implementor_gtype, &implementor_class, &implementor_vtable, &field_info);
329     if (field_info != NULL) {
330         GITypeInfo *type_info;
331         GIBaseInfo *interface_info;
332         GICallbackInfo *callback_info;
333         gint offset;
334
335         type_info = g_field_info_get_type (field_info);
336
337         interface_info = g_type_info_get_interface (type_info);
338         g_assert (g_base_info_get_type (interface_info) == GI_INFO_TYPE_CALLBACK);
339
340         callback_info = (GICallbackInfo*) interface_info;
341         offset = g_field_info_get_offset (field_info);
342         method_ptr = G_STRUCT_MEMBER_P (implementor_vtable, offset);
343
344         closure = _pygi_make_native_closure ( (GICallableInfo*) callback_info,
345                                               GI_SCOPE_TYPE_NOTIFIED, py_function, NULL);
346
347         *method_ptr = closure->closure;
348
349         g_base_info_unref (interface_info);
350         g_base_info_unref (type_info);
351         g_base_info_unref (field_info);
352     }
353     g_type_class_unref (implementor_class);
354
355     Py_RETURN_NONE;
356 }
357
358 #if 0
359 /* Not used, left around for future reference */
360 static PyObject *
361 _wrap_pyg_has_vfunc_implementation (PyObject *self, PyObject *args)
362 {
363     PyGIBaseInfo *py_info;
364     PyObject *py_type;
365     PyObject *py_ret;
366     gpointer implementor_class = NULL;
367     gpointer implementor_vtable = NULL;
368     GType implementor_gtype = 0;
369     GIFieldInfo *field_info = NULL;
370
371     if (!PyArg_ParseTuple (args, "O!O!:has_vfunc_implementation",
372                            &PyGIBaseInfo_Type, &py_info,
373                            &PyGTypeWrapper_Type, &py_type))
374         return NULL;
375
376     implementor_gtype = pyg_type_from_object (py_type);
377     g_assert (G_TYPE_IS_CLASSED (implementor_gtype));
378
379     py_ret = Py_False;
380     find_vfunc_info (py_info->info, implementor_gtype, &implementor_class, &implementor_vtable, &field_info);
381     if (field_info != NULL) {
382         gpointer *method_ptr;
383         gint offset;
384
385         offset = g_field_info_get_offset (field_info);
386         method_ptr = G_STRUCT_MEMBER_P (implementor_vtable, offset);
387         if (*method_ptr != NULL) {
388             py_ret = Py_True;
389         }
390
391         g_base_info_unref (field_info);
392     }
393     g_type_class_unref (implementor_class);
394
395     Py_INCREF(py_ret);
396     return py_ret;
397 }
398 #endif
399
400 static PyObject *
401 _wrap_pyg_variant_new_tuple (PyObject *self, PyObject *args)
402 {
403     PyObject *py_values;
404     GVariant **values = NULL;
405     GVariant *variant = NULL;
406     PyObject *py_variant = NULL;
407     PyObject *py_type;
408     gssize i;
409
410     if (!PyArg_ParseTuple (args, "O!:variant_new_tuple",
411                            &PyTuple_Type, &py_values)) {
412         return NULL;
413     }
414
415     py_type = _pygi_type_import_by_name ("GLib", "Variant");
416
417     values = g_newa (GVariant*, PyTuple_Size (py_values));
418
419     for (i = 0; i < PyTuple_Size (py_values); i++) {
420         PyObject *value = PyTuple_GET_ITEM (py_values, i);
421
422         if (!PyObject_IsInstance (value, py_type)) {
423             PyErr_Format (PyExc_TypeError, "argument %" G_GSSIZE_FORMAT " is not a GLib.Variant", i);
424             return NULL;
425         }
426
427         values[i] = (GVariant *) ( (PyGPointer *) value)->pointer;
428     }
429
430     variant = g_variant_new_tuple (values, PyTuple_Size (py_values));
431
432     py_variant = _pygi_struct_new ( (PyTypeObject *) py_type, variant, FALSE);
433
434     return py_variant;
435 }
436
437 static PyObject *
438 _wrap_pyg_variant_type_from_string (PyObject *self, PyObject *args)
439 {
440     char *type_string;
441     PyObject *py_type;
442     PyObject *py_variant = NULL;
443
444     if (!PyArg_ParseTuple (args, "s:variant_type_from_string",
445                            &type_string)) {
446         return NULL;
447     }
448
449     py_type = _pygi_type_import_by_name ("GLib", "VariantType");
450
451     py_variant = _pygi_boxed_new ( (PyTypeObject *) py_type, type_string, FALSE);
452
453     return py_variant;
454 }
455
456 static PyMethodDef _gi_functions[] = {
457     { "enum_add", (PyCFunction) _wrap_pyg_enum_add, METH_VARARGS | METH_KEYWORDS },
458     { "enum_register_new_gtype_and_add", (PyCFunction) _wrap_pyg_enum_register_new_gtype_and_add, METH_VARARGS | METH_KEYWORDS },
459     { "flags_add", (PyCFunction) _wrap_pyg_flags_add, METH_VARARGS | METH_KEYWORDS },
460     { "flags_register_new_gtype_and_add", (PyCFunction) _wrap_pyg_flags_register_new_gtype_and_add, METH_VARARGS | METH_KEYWORDS },
461
462     { "register_interface_info", (PyCFunction) _wrap_pyg_register_interface_info, METH_VARARGS },
463     { "hook_up_vfunc_implementation", (PyCFunction) _wrap_pyg_hook_up_vfunc_implementation, METH_VARARGS },
464     { "variant_new_tuple", (PyCFunction) _wrap_pyg_variant_new_tuple, METH_VARARGS },
465     { "variant_type_from_string", (PyCFunction) _wrap_pyg_variant_type_from_string, METH_VARARGS },
466     { NULL, NULL, 0 }
467 };
468
469 static struct PyGI_API CAPI = {
470   pygi_type_import_by_g_type_real,
471   pygi_get_property_value_real,
472   pygi_set_property_value_real,
473   pygi_signal_closure_new_real,
474   pygi_register_foreign_struct_real,
475 };
476
477 PYGLIB_MODULE_START(_gi, "_gi")
478 {
479     PyObject *api;
480
481     if (pygobject_init (-1, -1, -1) == NULL) {
482         return PYGLIB_MODULE_ERROR_RETURN;
483     }
484
485     if (_pygobject_import() < 0) {
486         return PYGLIB_MODULE_ERROR_RETURN;
487     }
488
489     _pygi_repository_register_types (module);
490     _pygi_info_register_types (module);
491     _pygi_struct_register_types (module);
492     _pygi_boxed_register_types (module);
493     _pygi_argument_init();
494
495     api = PYGLIB_CPointer_WrapPointer ( (void *) &CAPI, "gi._API");
496     if (api == NULL) {
497         return PYGLIB_MODULE_ERROR_RETURN;
498     }
499     PyModule_AddObject (module, "_API", api);
500 }
501 PYGLIB_MODULE_END