eafaca3185ad7c5854a770aa384cea048eea2b4b
[platform/upstream/pygobject2.git] / gi / pygi-foreign.c
1 /* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
2 /*
3  * Copyright (c) 2010  litl, LLC
4  * Copyright (c) 2010  Collabora Ltd. <http://www.collabora.co.uk/>
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22  * IN THE SOFTWARE.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 #  include <config.h>
27 #endif
28
29 #include "pygi-foreign.h"
30 #include "pygi-foreign-gvariant.h"
31
32 #include <girepository.h>
33
34 typedef struct {
35     const char *namespace;
36     const char *name;
37     PyGIArgOverrideToGIArgumentFunc to_func;
38     PyGIArgOverrideFromGIArgumentFunc from_func;
39     PyGIArgOverrideReleaseFunc release_func;
40 } PyGIForeignStruct;
41
42 static GPtrArray *foreign_structs = NULL;
43
44 void
45 init_foreign_structs ()
46 {
47     foreign_structs = g_ptr_array_new ();
48
49     pygi_register_foreign_struct ("GLib",
50                                   "Variant",
51                                   g_variant_to_arg,
52                                   g_variant_from_arg,
53                                   g_variant_release_foreign);
54 }
55
56 static PyGIForeignStruct *
57 do_lookup (const gchar *namespace, const gchar *name)
58 {
59     gint i;
60     for (i = 0; i < foreign_structs->len; i++) {
61         PyGIForeignStruct *foreign_struct = \
62                 g_ptr_array_index (foreign_structs, i);
63
64         if ( (strcmp (namespace, foreign_struct->namespace) == 0) &&
65                 (strcmp (name, foreign_struct->name) == 0)) {
66             return foreign_struct;
67         }
68     }
69     return NULL;
70 }
71
72 static PyGIForeignStruct *
73 pygi_struct_foreign_lookup (GIBaseInfo *base_info)
74 {
75     PyGIForeignStruct *result;
76     const gchar *namespace = g_base_info_get_namespace (base_info);
77     const gchar *name = g_base_info_get_name (base_info);
78
79     if (foreign_structs == NULL) {
80         init_foreign_structs ();
81     }
82
83     result = do_lookup (namespace, name);
84
85     if (result == NULL) {
86         gchar *module_name = g_strconcat ("gi._gi_", namespace, NULL);
87         PyObject *module = PyImport_ImportModule (module_name);
88
89         g_free (module_name);
90
91         if (module == NULL)
92             PyErr_Clear ();
93         else {
94             Py_DECREF (module);
95             result = do_lookup (namespace, name);
96         }
97     }
98
99     if (result == NULL) {
100         PyErr_Format (PyExc_TypeError,
101                       "Couldn't find conversion for foreign struct '%s.%s'",
102                       namespace,
103                       name);
104     }
105
106     return result;
107 }
108
109 PyObject *
110 pygi_struct_foreign_convert_to_g_argument (PyObject        *value,
111                                            GIInterfaceInfo *iface_info,
112                                            GITransfer       transfer,
113                                            GIArgument      *arg)
114 {
115     GIBaseInfo *base_info = (GIBaseInfo *) iface_info;
116     PyGIForeignStruct *foreign_struct = pygi_struct_foreign_lookup (base_info);
117
118     if (foreign_struct == NULL)
119         return NULL;
120
121     if (!foreign_struct->to_func (value, iface_info, transfer, arg))
122         return NULL;
123
124     Py_RETURN_NONE;
125 }
126
127 PyObject *
128 pygi_struct_foreign_convert_from_g_argument (GIInterfaceInfo *iface_info,
129                                              GIArgument      *arg)
130 {
131     GIBaseInfo *base_info = (GIBaseInfo *) iface_info;
132     PyGIForeignStruct *foreign_struct = pygi_struct_foreign_lookup (base_info);
133
134     if (foreign_struct == NULL)
135         return NULL;
136
137     return foreign_struct->from_func (iface_info, arg);
138 }
139
140 PyObject *
141 pygi_struct_foreign_release (GIBaseInfo *base_info,
142                              gpointer    struct_)
143 {
144     PyGIForeignStruct *foreign_struct = pygi_struct_foreign_lookup (base_info);
145
146     if (foreign_struct == NULL)
147         return NULL;
148
149     if (!foreign_struct->release_func)
150         Py_RETURN_NONE;
151
152     if (!foreign_struct->release_func (base_info, struct_))
153         return NULL;
154
155     Py_RETURN_NONE;
156 }
157
158 void
159 pygi_register_foreign_struct_real (const char* namespace_,
160                                    const char* name,
161                                    PyGIArgOverrideToGIArgumentFunc to_func,
162                                    PyGIArgOverrideFromGIArgumentFunc from_func,
163                                    PyGIArgOverrideReleaseFunc release_func)
164 {
165     PyGIForeignStruct *new_struct = g_slice_new (PyGIForeignStruct);
166     new_struct->namespace = namespace_;
167     new_struct->name = name;
168     new_struct->to_func = to_func;
169     new_struct->from_func = from_func;
170     new_struct->release_func = release_func;
171
172     g_ptr_array_add (foreign_structs, new_struct);
173 }