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