1 /* GObject introspection: Helper functions for ffi integration
3 * Copyright (C) 2008 Red Hat, Inc
4 * Copyright (C) 2005 Matthias Clasen
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.
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.
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.
22 #include <sys/types.h>
30 #include "girepository.h"
33 g_ir_ffi_get_ffi_type (GITypeTag tag)
37 case GI_TYPE_TAG_VOID:
38 return &ffi_type_void;
39 case GI_TYPE_TAG_BOOLEAN:
40 return &ffi_type_uint;
41 case GI_TYPE_TAG_INT8:
42 return &ffi_type_sint8;
43 case GI_TYPE_TAG_UINT8:
44 return &ffi_type_uint8;
45 case GI_TYPE_TAG_INT16:
46 return &ffi_type_sint16;
47 case GI_TYPE_TAG_UINT16:
48 return &ffi_type_uint16;
49 case GI_TYPE_TAG_INT32:
50 return &ffi_type_sint32;
51 case GI_TYPE_TAG_UINT32:
52 return &ffi_type_uint32;
53 case GI_TYPE_TAG_INT64:
54 return &ffi_type_sint64;
55 case GI_TYPE_TAG_UINT64:
56 return &ffi_type_uint64;
57 case GI_TYPE_TAG_SHORT:
58 return &ffi_type_sshort;
59 case GI_TYPE_TAG_USHORT:
60 return &ffi_type_ushort;
62 return &ffi_type_sint;
63 case GI_TYPE_TAG_UINT:
64 return &ffi_type_uint;
65 case GI_TYPE_TAG_SSIZE:
66 #if GLIB_SIZEOF_SIZE_T == 4
67 return &ffi_type_sint32;
68 #elif GLIB_SIZEOF_SIZE_T == 8
69 return &ffi_type_sint64;
71 # error "Unexpected size for size_t: not 4 or 8"
73 case GI_TYPE_TAG_LONG:
74 return &ffi_type_slong;
75 case GI_TYPE_TAG_SIZE:
76 case GI_TYPE_TAG_GTYPE:
77 #if GLIB_SIZEOF_SIZE_T == 4
78 return &ffi_type_uint32;
79 #elif GLIB_SIZEOF_SIZE_T == 8
80 return &ffi_type_uint64;
82 # error "Unexpected size for size_t: not 4 or 8"
84 case GI_TYPE_TAG_TIME_T:
85 #if SIZEOF_TIME_T == 4
86 return &ffi_type_sint32;
87 #elif SIZEOF_TIME_T == 8
88 return &ffi_type_sint64;
90 # error "Unexpected size for time_t: not 4 or 8"
92 case GI_TYPE_TAG_ULONG:
93 return &ffi_type_ulong;
94 case GI_TYPE_TAG_FLOAT:
95 return &ffi_type_float;
96 case GI_TYPE_TAG_DOUBLE:
97 return &ffi_type_double;
98 case GI_TYPE_TAG_UTF8:
99 case GI_TYPE_TAG_FILENAME:
100 case GI_TYPE_TAG_ARRAY:
101 case GI_TYPE_TAG_INTERFACE:
102 case GI_TYPE_TAG_GLIST:
103 case GI_TYPE_TAG_GSLIST:
104 case GI_TYPE_TAG_GHASH:
105 case GI_TYPE_TAG_ERROR:
106 return &ffi_type_pointer;
109 g_assert_not_reached ();
115 g_ir_ffi_convert_arguments(GICallableInfo *callable_info, void **args)
119 GITypeInfo *arg_type;
123 num_args = g_callable_info_get_n_args (callable_info);
124 g_args = g_new0 (GArgument, num_args);
126 for (i = 0; i < num_args; i++)
128 arg_info = g_callable_info_get_arg (callable_info, i);
129 arg_type = g_arg_info_get_type (arg_info);
130 tag = g_type_info_get_tag (arg_type);
134 case GI_TYPE_TAG_BOOLEAN:
135 g_args[i].v_boolean = *(gboolean *) args[i];
137 case GI_TYPE_TAG_INT8:
138 g_args[i].v_int8 = *(gint8 *) args[i];
140 case GI_TYPE_TAG_UINT8:
141 g_args[i].v_uint8 = *(guint8 *) args[i];
143 case GI_TYPE_TAG_INT16:
144 g_args[i].v_int16 = *(gint16 *) args[i];
146 case GI_TYPE_TAG_UINT16:
147 g_args[i].v_uint16 = *(guint16 *) args[i];
149 case GI_TYPE_TAG_INT32:
150 g_args[i].v_int32 = *(gint32 *) args[i];
152 case GI_TYPE_TAG_UINT32:
153 g_args[i].v_uint32 = *(guint32 *) args[i];
155 case GI_TYPE_TAG_LONG:
156 g_args[i].v_long = *(glong *) args[i];
158 case GI_TYPE_TAG_INT64:
159 g_args[i].v_int64 = *(gint64 *) args[i];
161 case GI_TYPE_TAG_ULONG:
162 g_args[i].v_ulong = *(gulong *) args[i];
164 case GI_TYPE_TAG_UINT64:
165 g_args[i].v_uint64 = *(guint64 *) args[i];
167 case GI_TYPE_TAG_INT:
168 g_args[i].v_int = *(gint *) args[i];
170 case GI_TYPE_TAG_SSIZE:
171 g_args[i].v_ssize = *(gssize *) args[i];
173 case GI_TYPE_TAG_SIZE:
174 g_args[i].v_size = *(gsize *) args[i];
176 case GI_TYPE_TAG_UINT:
177 g_args[i].v_uint = *(guint *) args[i];
179 case GI_TYPE_TAG_FLOAT:
180 g_args[i].v_float = *(gfloat *) args[i];
182 case GI_TYPE_TAG_DOUBLE:
183 g_args[i].v_double = *(gdouble *) args[i];
185 case GI_TYPE_TAG_UTF8:
186 g_args[i].v_string = *(gchar **) args[i];
188 case GI_TYPE_TAG_INTERFACE:
190 GIBaseInfo *interface;
191 GIInfoType interface_type;
193 interface = g_type_info_get_interface (arg_type);
194 interface_type = g_base_info_get_type (interface);
196 if (interface_type == GI_INFO_TYPE_OBJECT ||
197 interface_type == GI_INFO_TYPE_INTERFACE)
199 g_args[i].v_pointer = *(gpointer *) args[i];
200 g_base_info_unref (interface);
204 else if (interface_type == GI_INFO_TYPE_ENUM ||
205 interface_type == GI_INFO_TYPE_FLAGS)
207 g_args[i].v_double = *(double *) args[i];
208 g_base_info_unref (interface);
211 else if (interface_type == GI_INFO_TYPE_STRUCT)
213 g_args[i].v_pointer = *(gpointer *) args[i];
214 g_base_info_unref (interface);
218 g_base_info_unref (interface);
220 case GI_TYPE_TAG_GLIST:
221 case GI_TYPE_TAG_GSLIST:
222 g_args[i].v_pointer = *(gpointer *) args[i];
225 g_args[i].v_pointer = 0;
228 g_base_info_unref ((GIBaseInfo *) arg_info);
229 g_base_info_unref ((GIBaseInfo *) arg_type);
235 * g_callable_info_get_ffi_arg_types:
236 * @callable_info: a callable info from a typelib
238 * Return value: an array of ffi_type*. The array itself
239 * should be freed using g_free() after use.
242 g_callable_info_get_ffi_arg_types (GICallableInfo *callable_info)
244 ffi_type **arg_types;
247 g_return_val_if_fail (callable_info != NULL, NULL);
249 n_args = g_callable_info_get_n_args (callable_info);
251 arg_types = (ffi_type **) g_new0 (ffi_type *, n_args + 1);
253 for (i = 0; i < n_args; ++i)
255 GIArgInfo *arg_info = g_callable_info_get_arg (callable_info, i);
256 GITypeInfo *arg_type = g_arg_info_get_type (arg_info);
257 GITypeTag type_tag = g_type_info_get_tag (arg_type);
258 arg_types[i] = g_ir_ffi_get_ffi_type (type_tag);
259 g_base_info_unref ((GIBaseInfo *)arg_info);
260 g_base_info_unref ((GIBaseInfo *)arg_type);
262 arg_types[n_args] = NULL;
268 * g_callable_info_get_ffi_return_type:
269 * @callable_info: a callable info from a typelib
271 * Fetches the ffi_type for a corresponding return value of
273 * Return value: the ffi_type for the return value
276 g_callable_info_get_ffi_return_type (GICallableInfo *callable_info)
278 GITypeInfo *return_type;
281 g_return_val_if_fail (callable_info != NULL, NULL);
283 return_type = g_callable_info_get_return_type (callable_info);
284 type_tag = g_type_info_get_tag (return_type);
286 g_base_info_unref((GIBaseInfo*)return_type);
288 return g_ir_ffi_get_ffi_type (type_tag);
292 * g_callable_info_prepare_closure:
293 * @callable_info: a callable info from a typelib
294 * @cif: a ffi_cif structure
295 * @callback: the ffi callback
296 * @user_data: data to be passed into the callback
298 * Prepares a callback for ffi invocation.
300 * Note: this function requires the heap to be executable, which
301 * might not function properly on systems with SELinux enabled.
303 * Return value: the ffi_closure or NULL on error.
304 * The return value should be freed by calling g_callable_info_prepare_closure().
307 g_callable_info_prepare_closure (GICallableInfo *callable_info,
309 GIFFIClosureCallback callback,
312 ffi_closure *closure;
315 g_return_val_if_fail (callable_info != NULL, FALSE);
316 g_return_val_if_fail (cif != NULL, FALSE);
317 g_return_val_if_fail (callback != NULL, FALSE);
319 closure = mmap (NULL, sizeof (ffi_closure),
320 PROT_EXEC | PROT_READ | PROT_WRITE,
321 MAP_ANON | MAP_PRIVATE, -1, sysconf (_SC_PAGE_SIZE));
324 g_warning("mmap failed: %s\n", strerror(errno));
328 status = ffi_prep_cif (cif, FFI_DEFAULT_ABI,
329 g_callable_info_get_n_args (callable_info),
330 g_callable_info_get_ffi_return_type (callable_info),
331 g_callable_info_get_ffi_arg_types (callable_info));
332 if (status != FFI_OK)
334 g_warning("ffi_prep_cif failed: %d\n", status);
335 munmap(closure, sizeof (closure));
339 status = ffi_prep_closure (closure, cif, callback, user_data);
340 if (status != FFI_OK)
342 g_warning ("ffi_prep_closure failed: %d\n", status);
343 munmap(closure, sizeof (closure));
347 if (mprotect(closure, sizeof (closure), PROT_READ | PROT_EXEC) == -1)
349 g_warning ("ffi_prep_closure failed: %s\n", strerror(errno));
350 munmap(closure, sizeof (closure));
358 * g_callable_info_free_closure:
359 * @callable_info: a callable info from a typelib
360 * @closure: ffi closure
362 * Frees a ffi_closure returned from g_callable_info_prepare_closure()
365 g_callable_info_free_closure (GICallableInfo *callable_info,
366 ffi_closure *closure)
368 munmap(closure, sizeof (closure));