1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
2 * GObject introspection: Callable implementation
3 *
4 * Copyright (C) 2005 Matthias Clasen
5 * Copyright (C) 2008,2009 Red Hat, Inc.
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 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
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
21 */
22
23 #include "config.h"
24
25 #include <stdlib.h>
26
27 #include <glib.h>
28
29 #include <girepository.h>
30 #include "girepository-private.h"
31 #include "gitypelib-internal.h"
32 #include "girffi.h"
33
34 /* GICallableInfo functions */
35
36 /**
37 * SECTION:gicallableinfo
38 * @title: GICallableInfo
39 * @short_description: Struct representing a callable
40 *
41 * GICallableInfo represents an entity which is callable.
42 * Currently a function (#GIFunctionInfo), virtual function,
43 * (#GIVFuncInfo) or callback (#GICallbackInfo).
44 *
45 * A callable has a list of arguments (#GIArgInfo), a return type,
46 * direction and a flag which decides if it returns null.
47 *
48 * <refsect1 id="gi-gicallableinfo.struct-hierarchy" role="struct_hierarchy">
49 * <title role="struct_hierarchy.title">Struct hierarchy</title>
50 * <synopsis>
51 * <link linkend="GIBaseInfo">GIBaseInfo</link>
52 * +----GICallableInfo
53 * +----<link linkend="gi-GIFunctionInfo">GIFunctionInfo</link>
54 * +----<link linkend="gi-GISignalInfo">GISignalInfo</link>
55 * +----<link linkend="gi-GIVFuncInfo">GIVFuncInfo</link>
56 * </synopsis>
57 * </refsect1>
58 */
59
60 static guint32
signature_offset(GICallableInfo * info)61 signature_offset (GICallableInfo *info)
62 {
63 GIRealInfo *rinfo = (GIRealInfo*)info;
64 int sigoff = -1;
65
66 switch (rinfo->type)
67 {
68 case GI_INFO_TYPE_FUNCTION:
69 sigoff = G_STRUCT_OFFSET (FunctionBlob, signature);
70 break;
71 case GI_INFO_TYPE_VFUNC:
72 sigoff = G_STRUCT_OFFSET (VFuncBlob, signature);
73 break;
74 case GI_INFO_TYPE_CALLBACK:
75 sigoff = G_STRUCT_OFFSET (CallbackBlob, signature);
76 break;
77 case GI_INFO_TYPE_SIGNAL:
78 sigoff = G_STRUCT_OFFSET (SignalBlob, signature);
79 break;
80 default:
81 g_assert_not_reached ();
82 }
83 if (sigoff >= 0)
84 return *(guint32 *)&rinfo->typelib->data[rinfo->offset + sigoff];
85 return 0;
86 }
87
88 /**
89 * g_callable_info_can_throw_gerror:
90 * @info: a #GICallableInfo
91 *
92 * TODO
93 *
94 * Since: 1.34
95 * Returns: %TRUE if this #GICallableInfo can throw a #GError
96 */
97 gboolean
g_callable_info_can_throw_gerror(GICallableInfo * info)98 g_callable_info_can_throw_gerror (GICallableInfo *info)
99 {
100 GIRealInfo *rinfo = (GIRealInfo*)info;
101 SignatureBlob *signature;
102
103 signature = (SignatureBlob *)&rinfo->typelib->data[signature_offset (info)];
104 if (signature->throws)
105 return TRUE;
106
107 /* Functions and VFuncs store "throws" in their own blobs.
108 * This info was additionally added to the SignatureBlob
109 * to support the other callables. For Functions and VFuncs,
110 * also check their legacy flag for compatibility.
111 */
112 switch (rinfo->type) {
113 case GI_INFO_TYPE_FUNCTION:
114 {
115 FunctionBlob *blob;
116 blob = (FunctionBlob *)&rinfo->typelib->data[rinfo->offset];
117 return blob->throws;
118 }
119 case GI_INFO_TYPE_VFUNC:
120 {
121 VFuncBlob *blob;
122 blob = (VFuncBlob *)&rinfo->typelib->data[rinfo->offset];
123 return blob->throws;
124 }
125 case GI_INFO_TYPE_CALLBACK:
126 case GI_INFO_TYPE_SIGNAL:
127 return FALSE;
128 default:
129 g_assert_not_reached ();
130 }
131 }
132
133 /**
134 * g_callable_info_is_method:
135 * @info: a #GICallableInfo
136 *
137 * Determines if the callable info is a method. For #GIVFuncInfo<!-- -->s,
138 * #GICallbackInfo<!-- -->s, and #GISignalInfo<!-- -->s,
139 * this is always true. Otherwise, this looks at the %GI_FUNCTION_IS_METHOD
140 * flag on the #GIFunctionInfo.
141 *
142 * Concretely, this function returns whether g_callable_info_get_n_args()
143 * matches the number of arguments in the raw C method. For methods, there
144 * is one more C argument than is exposed by introspection: the "self"
145 * or "this" object.
146 *
147 * Returns: %TRUE if @info is a method, %FALSE otherwise
148 * Since: 1.34
149 */
150 gboolean
g_callable_info_is_method(GICallableInfo * info)151 g_callable_info_is_method (GICallableInfo *info)
152 {
153 GIRealInfo *rinfo = (GIRealInfo*)info;
154 switch (rinfo->type) {
155 case GI_INFO_TYPE_FUNCTION:
156 {
157 FunctionBlob *blob;
158 blob = (FunctionBlob *)&rinfo->typelib->data[rinfo->offset];
159 return (!blob->constructor && !blob->is_static);
160 }
161 case GI_INFO_TYPE_VFUNC:
162 case GI_INFO_TYPE_SIGNAL:
163 return TRUE;
164 case GI_INFO_TYPE_CALLBACK:
165 return FALSE;
166 default:
167 g_assert_not_reached ();
168 }
169 }
170
171 /**
172 * g_callable_info_get_return_type:
173 * @info: a #GICallableInfo
174 *
175 * Obtain the return type of a callable item as a #GITypeInfo.
176 *
177 * Returns: (transfer full): the #GITypeInfo. Free the struct by calling
178 * g_base_info_unref() when done.
179 */
180 GITypeInfo *
g_callable_info_get_return_type(GICallableInfo * info)181 g_callable_info_get_return_type (GICallableInfo *info)
182 {
183 GIRealInfo *rinfo = (GIRealInfo *)info;
184 guint32 offset;
185
186 g_return_val_if_fail (info != NULL, NULL);
187 g_return_val_if_fail (GI_IS_CALLABLE_INFO (info), NULL);
188
189 offset = signature_offset (info);
190
191 return _g_type_info_new ((GIBaseInfo*)info, rinfo->typelib, offset);
192 }
193
194
195 /**
196 * g_callable_info_load_return_type:
197 * @info: a #GICallableInfo
198 * @type: (out caller-allocates): Initialized with return type of @info
199 *
200 * Obtain information about a return value of callable; this
201 * function is a variant of g_callable_info_get_return_type() designed for stack
202 * allocation.
203 *
204 * The initialized @type must not be referenced after @info is deallocated.
205 */
206 void
g_callable_info_load_return_type(GICallableInfo * info,GITypeInfo * type)207 g_callable_info_load_return_type (GICallableInfo *info,
208 GITypeInfo *type)
209 {
210 GIRealInfo *rinfo = (GIRealInfo *)info;
211 guint32 offset;
212
213 g_return_if_fail (info != NULL);
214 g_return_if_fail (GI_IS_CALLABLE_INFO (info));
215
216 offset = signature_offset (info);
217
218 _g_type_info_init (type, (GIBaseInfo*)info, rinfo->typelib, offset);
219 }
220
221 /**
222 * g_callable_info_may_return_null:
223 * @info: a #GICallableInfo
224 *
225 * See if a callable could return %NULL.
226 *
227 * Returns: %TRUE if callable could return %NULL
228 */
229 gboolean
g_callable_info_may_return_null(GICallableInfo * info)230 g_callable_info_may_return_null (GICallableInfo *info)
231 {
232 GIRealInfo *rinfo = (GIRealInfo *)info;
233 SignatureBlob *blob;
234
235 g_return_val_if_fail (info != NULL, FALSE);
236 g_return_val_if_fail (GI_IS_CALLABLE_INFO (info), FALSE);
237
238 blob = (SignatureBlob *)&rinfo->typelib->data[signature_offset (info)];
239
240 return blob->may_return_null;
241 }
242
243 /**
244 * g_callable_info_skip_return:
245 * @info: a #GICallableInfo
246 *
247 * See if a callable's return value is only useful in C.
248 *
249 * Returns: %TRUE if return value is only useful in C.
250 */
251 gboolean
g_callable_info_skip_return(GICallableInfo * info)252 g_callable_info_skip_return (GICallableInfo *info)
253 {
254 GIRealInfo *rinfo = (GIRealInfo *)info;
255 SignatureBlob *blob;
256
257 g_return_val_if_fail (info != NULL, FALSE);
258 g_return_val_if_fail (GI_IS_CALLABLE_INFO (info), FALSE);
259
260 blob = (SignatureBlob *)&rinfo->typelib->data[signature_offset (info)];
261
262 return blob->skip_return;
263 }
264
265 /**
266 * g_callable_info_get_caller_owns:
267 * @info: a #GICallableInfo
268 *
269 * See whether the caller owns the return value of this callable.
270 * #GITransfer contains a list of possible transfer values.
271 *
272 * Returns: the transfer mode for the return value of the callable
273 */
274 GITransfer
g_callable_info_get_caller_owns(GICallableInfo * info)275 g_callable_info_get_caller_owns (GICallableInfo *info)
276 {
277 GIRealInfo *rinfo = (GIRealInfo*) info;
278 SignatureBlob *blob;
279
280 g_return_val_if_fail (info != NULL, -1);
281 g_return_val_if_fail (GI_IS_CALLABLE_INFO (info), -1);
282
283 blob = (SignatureBlob *)&rinfo->typelib->data[signature_offset (info)];
284
285 if (blob->caller_owns_return_value)
286 return GI_TRANSFER_EVERYTHING;
287 else if (blob->caller_owns_return_container)
288 return GI_TRANSFER_CONTAINER;
289 else
290 return GI_TRANSFER_NOTHING;
291 }
292
293 /**
294 * g_callable_info_get_instance_ownership_transfer:
295 * @info: a #GICallableInfo
296 *
297 * Obtains the ownership transfer for the instance argument.
298 * #GITransfer contains a list of possible transfer values.
299 *
300 * Since: 1.42
301 * Returns: the transfer mode of the instance argument
302 */
303 GITransfer
g_callable_info_get_instance_ownership_transfer(GICallableInfo * info)304 g_callable_info_get_instance_ownership_transfer (GICallableInfo *info)
305 {
306 GIRealInfo *rinfo = (GIRealInfo*) info;
307 SignatureBlob *blob;
308
309 g_return_val_if_fail (info != NULL, -1);
310 g_return_val_if_fail (GI_IS_CALLABLE_INFO (info), -1);
311
312 blob = (SignatureBlob *)&rinfo->typelib->data[signature_offset (info)];
313
314 if (blob->instance_transfer_ownership)
315 return GI_TRANSFER_EVERYTHING;
316 else
317 return GI_TRANSFER_NOTHING;
318 }
319
320 /**
321 * g_callable_info_get_n_args:
322 * @info: a #GICallableInfo
323 *
324 * Obtain the number of arguments (both IN and OUT) for this callable.
325 *
326 * Returns: The number of arguments this callable expects.
327 */
328 gint
g_callable_info_get_n_args(GICallableInfo * info)329 g_callable_info_get_n_args (GICallableInfo *info)
330 {
331 GIRealInfo *rinfo = (GIRealInfo *)info;
332 gint offset;
333 SignatureBlob *blob;
334
335 g_return_val_if_fail (info != NULL, -1);
336 g_return_val_if_fail (GI_IS_CALLABLE_INFO (info), -1);
337
338 offset = signature_offset (info);
339 blob = (SignatureBlob *)&rinfo->typelib->data[offset];
340
341 return blob->n_arguments;
342 }
343
344 /**
345 * g_callable_info_get_arg:
346 * @info: a #GICallableInfo
347 * @n: the argument index to fetch
348 *
349 * Obtain information about a particular argument of this callable.
350 *
351 * Returns: (transfer full): the #GIArgInfo. Free it with
352 * g_base_info_unref() when done.
353 */
354 GIArgInfo *
g_callable_info_get_arg(GICallableInfo * info,gint n)355 g_callable_info_get_arg (GICallableInfo *info,
356 gint n)
357 {
358 GIRealInfo *rinfo = (GIRealInfo *)info;
359 Header *header;
360 gint offset;
361
362 g_return_val_if_fail (info != NULL, NULL);
363 g_return_val_if_fail (GI_IS_CALLABLE_INFO (info), NULL);
364
365 offset = signature_offset (info);
366 header = (Header *)rinfo->typelib->data;
367
368 return (GIArgInfo *) g_info_new (GI_INFO_TYPE_ARG, (GIBaseInfo*)info, rinfo->typelib,
369 offset + header->signature_blob_size + n * header->arg_blob_size);
370 }
371
372 /**
373 * g_callable_info_load_arg:
374 * @info: a #GICallableInfo
375 * @n: the argument index to fetch
376 * @arg: (out caller-allocates): Initialize with argument number @n
377 *
378 * Obtain information about a particular argument of this callable; this
379 * function is a variant of g_callable_info_get_arg() designed for stack
380 * allocation.
381 *
382 * The initialized @arg must not be referenced after @info is deallocated.
383 */
384 void
g_callable_info_load_arg(GICallableInfo * info,gint n,GIArgInfo * arg)385 g_callable_info_load_arg (GICallableInfo *info,
386 gint n,
387 GIArgInfo *arg)
388 {
389 GIRealInfo *rinfo = (GIRealInfo *)info;
390 Header *header;
391 gint offset;
392
393 g_return_if_fail (info != NULL);
394 g_return_if_fail (GI_IS_CALLABLE_INFO (info));
395
396 offset = signature_offset (info);
397 header = (Header *)rinfo->typelib->data;
398
399 _g_info_init ((GIRealInfo*)arg, GI_INFO_TYPE_ARG, rinfo->repository, (GIBaseInfo*)info, rinfo->typelib,
400 offset + header->signature_blob_size + n * header->arg_blob_size);
401 }
402
403 /**
404 * g_callable_info_get_return_attribute:
405 * @info: a #GICallableInfo
406 * @name: a freeform string naming an attribute
407 *
408 * Retrieve an arbitrary attribute associated with the return value.
409 *
410 * Returns: The value of the attribute, or %NULL if no such attribute exists
411 */
412 const gchar *
g_callable_info_get_return_attribute(GICallableInfo * info,const gchar * name)413 g_callable_info_get_return_attribute (GICallableInfo *info,
414 const gchar *name)
415 {
416 GIAttributeIter iter = { 0, };
417 gchar *curname, *curvalue;
418 while (g_callable_info_iterate_return_attributes (info, &iter, &curname, &curvalue))
419 {
420 if (g_strcmp0 (name, curname) == 0)
421 return (const gchar*) curvalue;
422 }
423
424 return NULL;
425 }
426
427 /**
428 * g_callable_info_iterate_return_attributes:
429 * @info: a #GICallableInfo
430 * @iterator: (inout): a #GIAttributeIter structure, must be initialized; see below
431 * @name: (out) (transfer none): Returned name, must not be freed
432 * @value: (out) (transfer none): Returned name, must not be freed
433 *
434 * Iterate over all attributes associated with the return value. The
435 * iterator structure is typically stack allocated, and must have its
436 * first member initialized to %NULL.
437 *
438 * Both the @name and @value should be treated as constants
439 * and must not be freed.
440 *
441 * See g_base_info_iterate_attributes() for an example of how to use a
442 * similar API.
443 *
444 * Returns: %TRUE if there are more attributes
445 */
446 gboolean
g_callable_info_iterate_return_attributes(GICallableInfo * info,GIAttributeIter * iterator,char ** name,char ** value)447 g_callable_info_iterate_return_attributes (GICallableInfo *info,
448 GIAttributeIter *iterator,
449 char **name,
450 char **value)
451 {
452 GIRealInfo *rinfo = (GIRealInfo *)info;
453 Header *header = (Header *)rinfo->typelib->data;
454 AttributeBlob *next, *after;
455 guint32 blob_offset;
456
457 after = (AttributeBlob *) &rinfo->typelib->data[header->attributes +
458 header->n_attributes * header->attribute_blob_size];
459
460 blob_offset = signature_offset (info);
461
462 if (iterator->data != NULL)
463 next = (AttributeBlob *) iterator->data;
464 else
465 next = _attribute_blob_find_first (info, blob_offset);
466
467 if (next == NULL || next->offset != blob_offset || next >= after)
468 return FALSE;
469
470 *name = (gchar*) g_typelib_get_string (rinfo->typelib, next->name);
471 *value = (gchar*) g_typelib_get_string (rinfo->typelib, next->value);
472 iterator->data = next + 1;
473
474 return TRUE;
475 }
476
477 /**
478 * gi_type_info_extract_ffi_return_value:
479 * @return_info: TODO
480 * @ffi_value: TODO
481 * @arg: (out caller-allocates): TODO
482 *
483 * Extract the correct bits from an ffi_arg return value into
484 * GIArgument: https://bugzilla.gnome.org/show_bug.cgi?id=665152
485 *
486 * Also see <citerefentry><refentrytitle>ffi_call</refentrytitle><manvolnum>3</manvolnum></citerefentry>
487 * - the storage requirements for return values are "special".
488 */
489 void
gi_type_info_extract_ffi_return_value(GITypeInfo * return_info,GIFFIReturnValue * ffi_value,GIArgument * arg)490 gi_type_info_extract_ffi_return_value (GITypeInfo *return_info,
491 GIFFIReturnValue *ffi_value,
492 GIArgument *arg)
493 {
494 switch (g_type_info_get_tag (return_info)) {
495 case GI_TYPE_TAG_INT8:
496 arg->v_int8 = (gint8) ffi_value->v_long;
497 break;
498 case GI_TYPE_TAG_UINT8:
499 arg->v_uint8 = (guint8) ffi_value->v_ulong;
500 break;
501 case GI_TYPE_TAG_INT16:
502 arg->v_int16 = (gint16) ffi_value->v_long;
503 break;
504 case GI_TYPE_TAG_UINT16:
505 arg->v_uint16 = (guint16) ffi_value->v_ulong;
506 break;
507 case GI_TYPE_TAG_INT32:
508 arg->v_int32 = (gint32) ffi_value->v_long;
509 break;
510 case GI_TYPE_TAG_UINT32:
511 case GI_TYPE_TAG_BOOLEAN:
512 case GI_TYPE_TAG_UNICHAR:
513 arg->v_uint32 = (guint32) ffi_value->v_ulong;
514 break;
515 case GI_TYPE_TAG_INT64:
516 arg->v_int64 = (gint64) ffi_value->v_int64;
517 break;
518 case GI_TYPE_TAG_UINT64:
519 arg->v_uint64 = (guint64) ffi_value->v_uint64;
520 break;
521 case GI_TYPE_TAG_FLOAT:
522 arg->v_float = ffi_value->v_float;
523 break;
524 case GI_TYPE_TAG_DOUBLE:
525 arg->v_double = ffi_value->v_double;
526 break;
527 case GI_TYPE_TAG_INTERFACE:
528 {
529 GIBaseInfo* interface_info;
530 GIInfoType interface_type;
531
532 interface_info = g_type_info_get_interface(return_info);
533 interface_type = g_base_info_get_type(interface_info);
534
535 switch(interface_type) {
536 case GI_INFO_TYPE_ENUM:
537 case GI_INFO_TYPE_FLAGS:
538 arg->v_int32 = (gint32) ffi_value->v_long;
539 break;
540 default:
541 arg->v_pointer = (gpointer) ffi_value->v_pointer;
542 break;
543 }
544
545 g_base_info_unref(interface_info);
546 }
547 break;
548 default:
549 arg->v_pointer = (gpointer) ffi_value->v_pointer;
550 break;
551 }
552 }
553
554 /**
555 * g_callable_info_invoke:
556 * @info: TODO
557 * @function: TODO
558 * @in_args: (array length=n_in_args): TODO
559 * @n_in_args: TODO
560 * @out_args: (array length=n_out_args): TODO
561 * @n_out_args: TODO
562 * @return_value: TODO
563 * @is_method: TODO
564 * @throws: TODO
565 * @error: TODO
566 *
567 * TODO
568 */
569 gboolean
g_callable_info_invoke(GIFunctionInfo * info,gpointer function,const GIArgument * in_args,int n_in_args,const GIArgument * out_args,int n_out_args,GIArgument * return_value,gboolean is_method,gboolean throws,GError ** error)570 g_callable_info_invoke (GIFunctionInfo *info,
571 gpointer function,
572 const GIArgument *in_args,
573 int n_in_args,
574 const GIArgument *out_args,
575 int n_out_args,
576 GIArgument *return_value,
577 gboolean is_method,
578 gboolean throws,
579 GError **error)
580 {
581 ffi_cif cif;
582 ffi_type *rtype;
583 ffi_type **atypes;
584 GITypeInfo *tinfo;
585 GITypeInfo *rinfo;
586 GITypeTag rtag;
587 GIArgInfo *ainfo;
588 gint n_args, n_invoke_args, in_pos, out_pos, i;
589 gpointer *args;
590 gboolean success = FALSE;
591 GError *local_error = NULL;
592 gpointer error_address = &local_error;
593 GIFFIReturnValue ffi_return_value;
594 gpointer return_value_p; /* Will point inside the union return_value */
595
596 rinfo = g_callable_info_get_return_type ((GICallableInfo *)info);
597 rtype = g_type_info_get_ffi_type (rinfo);
598 rtag = g_type_info_get_tag(rinfo);
599
600 in_pos = 0;
601 out_pos = 0;
602
603 n_args = g_callable_info_get_n_args ((GICallableInfo *)info);
604 if (is_method)
605 {
606 if (n_in_args == 0)
607 {
608 g_set_error (error,
609 G_INVOKE_ERROR,
610 G_INVOKE_ERROR_ARGUMENT_MISMATCH,
611 "Too few \"in\" arguments (handling this)");
612 goto out;
613 }
614 n_invoke_args = n_args+1;
615 in_pos++;
616 }
617 else
618 n_invoke_args = n_args;
619
620 if (throws)
621 /* Add an argument for the GError */
622 n_invoke_args ++;
623
624 atypes = g_alloca (sizeof (ffi_type*) * n_invoke_args);
625 args = g_alloca (sizeof (gpointer) * n_invoke_args);
626
627 if (is_method)
628 {
629 atypes[0] = &ffi_type_pointer;
630 args[0] = (gpointer) &in_args[0];
631 }
632 for (i = 0; i < n_args; i++)
633 {
634 int offset = (is_method ? 1 : 0);
635 ainfo = g_callable_info_get_arg ((GICallableInfo *)info, i);
636 switch (g_arg_info_get_direction (ainfo))
637 {
638 case GI_DIRECTION_IN:
639 tinfo = g_arg_info_get_type (ainfo);
640 atypes[i+offset] = g_type_info_get_ffi_type (tinfo);
641 g_base_info_unref ((GIBaseInfo *)ainfo);
642 g_base_info_unref ((GIBaseInfo *)tinfo);
643
644 if (in_pos >= n_in_args)
645 {
646 g_set_error (error,
647 G_INVOKE_ERROR,
648 G_INVOKE_ERROR_ARGUMENT_MISMATCH,
649 "Too few \"in\" arguments (handling in)");
650 goto out;
651 }
652
653 args[i+offset] = (gpointer)&in_args[in_pos];
654 in_pos++;
655
656 break;
657 case GI_DIRECTION_OUT:
658 atypes[i+offset] = &ffi_type_pointer;
659 g_base_info_unref ((GIBaseInfo *)ainfo);
660
661 if (out_pos >= n_out_args)
662 {
663 g_set_error (error,
664 G_INVOKE_ERROR,
665 G_INVOKE_ERROR_ARGUMENT_MISMATCH,
666 "Too few \"out\" arguments (handling out)");
667 goto out;
668 }
669
670 args[i+offset] = (gpointer)&out_args[out_pos];
671 out_pos++;
672 break;
673 case GI_DIRECTION_INOUT:
674 atypes[i+offset] = &ffi_type_pointer;
675 g_base_info_unref ((GIBaseInfo *)ainfo);
676
677 if (in_pos >= n_in_args)
678 {
679 g_set_error (error,
680 G_INVOKE_ERROR,
681 G_INVOKE_ERROR_ARGUMENT_MISMATCH,
682 "Too few \"in\" arguments (handling inout)");
683 goto out;
684 }
685
686 if (out_pos >= n_out_args)
687 {
688 g_set_error (error,
689 G_INVOKE_ERROR,
690 G_INVOKE_ERROR_ARGUMENT_MISMATCH,
691 "Too few \"out\" arguments (handling inout)");
692 goto out;
693 }
694
695 args[i+offset] = (gpointer)&in_args[in_pos];
696 in_pos++;
697 out_pos++;
698 break;
699 default:
700 g_base_info_unref ((GIBaseInfo *)ainfo);
701 g_assert_not_reached ();
702 }
703 }
704
705 if (throws)
706 {
707 args[n_invoke_args - 1] = &error_address;
708 atypes[n_invoke_args - 1] = &ffi_type_pointer;
709 }
710
711 if (in_pos < n_in_args)
712 {
713 g_set_error (error,
714 G_INVOKE_ERROR,
715 G_INVOKE_ERROR_ARGUMENT_MISMATCH,
716 "Too many \"in\" arguments (at end)");
717 goto out;
718 }
719 if (out_pos < n_out_args)
720 {
721 g_set_error (error,
722 G_INVOKE_ERROR,
723 G_INVOKE_ERROR_ARGUMENT_MISMATCH,
724 "Too many \"out\" arguments (at end)");
725 goto out;
726 }
727
728 if (ffi_prep_cif (&cif, FFI_DEFAULT_ABI, n_invoke_args, rtype, atypes) != FFI_OK)
729 goto out;
730
731 g_return_val_if_fail (return_value, FALSE);
732 /* See comment for GIFFIReturnValue above */
733 switch (rtag)
734 {
735 case GI_TYPE_TAG_FLOAT:
736 return_value_p = &ffi_return_value.v_float;
737 break;
738 case GI_TYPE_TAG_DOUBLE:
739 return_value_p = &ffi_return_value.v_double;
740 break;
741 case GI_TYPE_TAG_INT64:
742 case GI_TYPE_TAG_UINT64:
743 return_value_p = &ffi_return_value.v_uint64;
744 break;
745 default:
746 return_value_p = &ffi_return_value.v_long;
747 }
748 ffi_call (&cif, function, return_value_p, args);
749
750 if (local_error)
751 {
752 g_propagate_error (error, local_error);
753 success = FALSE;
754 }
755 else
756 {
757 gi_type_info_extract_ffi_return_value (rinfo, &ffi_return_value, return_value);
758 success = TRUE;
759 }
760 out:
761 g_base_info_unref ((GIBaseInfo *)rinfo);
762 return success;
763 }
764