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