Branch and submit for IVI panda
[profile/ivi/gobject-introspection.git] / girepository / ginvoke.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
2  * GObject introspection: Invoke functionality
3  *
4  * Copyright (C) 2005 Matthias Clasen
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 #include <stdlib.h>
23
24 #include <glib.h>
25 #include <glib-object.h>
26
27 #include <girepository.h>
28 #include "girffi.h"
29 #include "config.h"
30
31 static ffi_type *
32 value_to_ffi_type (const GValue *gvalue, gpointer *value)
33 {
34   ffi_type *rettype = NULL;
35   GType type = g_type_fundamental (G_VALUE_TYPE (gvalue));
36   g_assert (type != G_TYPE_INVALID);
37
38   switch (type)
39     {
40     case G_TYPE_BOOLEAN:
41     case G_TYPE_CHAR:
42     case G_TYPE_INT:
43       rettype = &ffi_type_sint;
44       *value = (gpointer)&(gvalue->data[0].v_int);
45       break;
46     case G_TYPE_UCHAR:
47     case G_TYPE_UINT:
48       rettype = &ffi_type_uint;
49       *value = (gpointer)&(gvalue->data[0].v_uint);
50       break;
51     case G_TYPE_STRING:
52     case G_TYPE_OBJECT:
53     case G_TYPE_BOXED:
54     case G_TYPE_POINTER:
55       rettype = &ffi_type_pointer;
56       *value = (gpointer)&(gvalue->data[0].v_pointer);
57       break;
58     case G_TYPE_FLOAT:
59       rettype = &ffi_type_float;
60       *value = (gpointer)&(gvalue->data[0].v_float);
61       break;
62     case G_TYPE_DOUBLE:
63       rettype = &ffi_type_double;
64       *value = (gpointer)&(gvalue->data[0].v_double);
65       break;
66     case G_TYPE_LONG:
67       rettype = &ffi_type_slong;
68       *value = (gpointer)&(gvalue->data[0].v_long);
69       break;
70     case G_TYPE_ULONG:
71       rettype = &ffi_type_ulong;
72       *value = (gpointer)&(gvalue->data[0].v_ulong);
73       break;
74     case G_TYPE_INT64:
75       rettype = &ffi_type_sint64;
76       *value = (gpointer)&(gvalue->data[0].v_int64);
77       break;
78     case G_TYPE_UINT64:
79       rettype = &ffi_type_uint64;
80       *value = (gpointer)&(gvalue->data[0].v_uint64);
81       break;
82     default:
83       rettype = &ffi_type_pointer;
84       *value = NULL;
85       g_warning ("Unsupported fundamental type: %s", g_type_name (type));
86       break;
87     }
88   return rettype;
89 }
90
91 /* See comment aboe set_gargument_from_ffi_return_value() */
92 static ffi_type *
93 g_value_to_ffi_return_type (const GValue *gvalue,
94                             const GIArgument *ffi_value,
95                             gpointer *value)
96 {
97   ffi_type *rettype = NULL;
98   GType type = g_type_fundamental (G_VALUE_TYPE (gvalue));
99   g_assert (type != G_TYPE_INVALID);
100
101   *value = (gpointer)&(ffi_value->v_long);
102
103   switch (type) {
104   case G_TYPE_CHAR:
105     rettype = &ffi_type_sint8;
106     break;
107   case G_TYPE_UCHAR:
108     rettype = &ffi_type_uint8;
109     break;
110   case G_TYPE_BOOLEAN:
111   case G_TYPE_INT:
112     rettype = &ffi_type_sint;
113     break;
114   case G_TYPE_UINT:
115     rettype = &ffi_type_uint;
116     break;
117   case G_TYPE_STRING:
118   case G_TYPE_OBJECT:
119   case G_TYPE_BOXED:
120   case G_TYPE_POINTER:
121     rettype = &ffi_type_pointer;
122     break;
123   case G_TYPE_FLOAT:
124     rettype = &ffi_type_float;
125     *value = (gpointer)&(ffi_value->v_float);
126     break;
127   case G_TYPE_DOUBLE:
128     rettype = &ffi_type_double;
129     *value = (gpointer)&(ffi_value->v_double);
130     break;
131   case G_TYPE_LONG:
132     rettype = &ffi_type_slong;
133     break;
134   case G_TYPE_ULONG:
135     rettype = &ffi_type_ulong;
136     break;
137   case G_TYPE_INT64:
138     rettype = &ffi_type_sint64;
139     *value = (gpointer)&(ffi_value->v_int64);
140     break;
141   case G_TYPE_UINT64:
142     rettype = &ffi_type_uint64;
143     *value = (gpointer)&(ffi_value->v_uint64);
144     break;
145   default:
146     rettype = &ffi_type_pointer;
147     *value = NULL;
148     g_warning ("Unsupported fundamental type: %s", g_type_name (type));
149     break;
150   }
151   return rettype;
152 }
153
154 static void
155 g_value_from_ffi_value (GValue           *gvalue,
156                         const GIArgument *value)
157 {
158   switch (g_type_fundamental (G_VALUE_TYPE (gvalue))) {
159   case G_TYPE_INT:
160       g_value_set_int (gvalue, (gint)value->v_long);
161       break;
162   case G_TYPE_FLOAT:
163       g_value_set_float (gvalue, (gfloat)value->v_float);
164       break;
165   case G_TYPE_DOUBLE:
166       g_value_set_double (gvalue, (gdouble)value->v_double);
167       break;
168   case G_TYPE_BOOLEAN:
169       g_value_set_boolean (gvalue, (gboolean)value->v_long);
170       break;
171   case G_TYPE_STRING:
172       g_value_set_string (gvalue, (gchar*)value->v_pointer);
173       break;
174   case G_TYPE_CHAR:
175       g_value_set_char (gvalue, (gchar)value->v_long);
176       break;
177   case G_TYPE_UCHAR:
178       g_value_set_uchar (gvalue, (guchar)value->v_ulong);
179       break;
180   case G_TYPE_UINT:
181       g_value_set_uint (gvalue, (guint)value->v_ulong);
182       break;
183   case G_TYPE_POINTER:
184       g_value_set_pointer (gvalue, (gpointer)value->v_pointer);
185       break;
186   case G_TYPE_LONG:
187       g_value_set_long (gvalue, (glong)value->v_long);
188       break;
189   case G_TYPE_ULONG:
190       g_value_set_ulong (gvalue, (gulong)value->v_ulong);
191       break;
192   case G_TYPE_INT64:
193       g_value_set_int64 (gvalue, (gint64)value->v_int64);
194       break;
195   case G_TYPE_UINT64:
196       g_value_set_uint64 (gvalue, (guint64)value->v_uint64);
197       break;
198   case G_TYPE_BOXED:
199       g_value_set_boxed (gvalue, (gpointer)value->v_pointer);
200       break;
201   default:
202     g_warning ("Unsupported fundamental type: %s",
203                g_type_name (g_type_fundamental (G_VALUE_TYPE (gvalue))));
204   }
205
206 }
207
208 void
209 gi_cclosure_marshal_generic (GClosure *closure,
210                              GValue *return_gvalue,
211                              guint n_param_values,
212                              const GValue *param_values,
213                              gpointer invocation_hint,
214                              gpointer marshal_data)
215 {
216   GIArgument return_ffi_value;
217   ffi_type *rtype;
218   void *rvalue;
219   int n_args;
220   ffi_type **atypes;
221   void **args;
222   int i;
223   ffi_cif cif;
224   GCClosure *cc = (GCClosure*) closure;
225
226   if (return_gvalue && G_VALUE_TYPE (return_gvalue))
227     {
228       rtype = g_value_to_ffi_return_type (return_gvalue, &return_ffi_value,
229                                           &rvalue);
230     }
231   else
232     {
233       rtype = &ffi_type_void;
234       rvalue = &return_ffi_value.v_long;
235     }
236
237   n_args = n_param_values + 1;
238   atypes = g_alloca (sizeof (ffi_type *) * n_args);
239   args =  g_alloca (sizeof (gpointer) * n_args);
240
241   if (n_param_values > 0)
242     {
243       if (G_CCLOSURE_SWAP_DATA (closure))
244         {
245           atypes[n_args-1] = value_to_ffi_type (param_values + 0,
246                                                 &args[n_args-1]);
247           atypes[0] = &ffi_type_pointer;
248           args[0] = &closure->data;
249         }
250       else
251         {
252           atypes[0] = value_to_ffi_type (param_values + 0, &args[0]);
253           atypes[n_args-1] = &ffi_type_pointer;
254           args[n_args-1] = &closure->data;
255         }
256     }
257   else
258     {
259       atypes[0] = &ffi_type_pointer;
260       args[0] = &closure->data;
261     }
262
263   for (i = 1; i < n_args - 1; i++)
264     atypes[i] = value_to_ffi_type (param_values + i, &args[i]);
265
266   if (ffi_prep_cif (&cif, FFI_DEFAULT_ABI, n_args, rtype, atypes) != FFI_OK)
267     return;
268
269   ffi_call (&cif, marshal_data ? marshal_data : cc->callback, rvalue, args);
270
271   if (return_gvalue && G_VALUE_TYPE (return_gvalue))
272     g_value_from_ffi_value (return_gvalue, &return_ffi_value);
273 }