1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
2 * GObject introspection: Callable implementation
4 * Copyright (C) 2005 Matthias Clasen
5 * Copyright (C) 2008,2009 Red Hat, Inc.
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.
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.
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.
29 #include <girepository.h>
30 #include "girepository-private.h"
31 #include "gitypelib-internal.h"
34 /* GICallableInfo functions */
37 * SECTION:gicallableinfo
38 * @title: GICallableInfo
39 * @short_description: Struct representing a callable
41 * GICallableInfo represents an entity which is callable.
42 * Currently a function (#GIFunctionInfo), virtual function,
43 * (#GIVFuncInfo) or callback (#GICallbackInfo).
45 * A callable has a list of arguments (#GIArgInfo), a return type,
46 * direction and a flag which decides if it returns null.
48 * <refsect1 id="gi-gicallableinfo.struct-hierarchy" role="struct_hierarchy">
49 * <title role="struct_hierarchy.title">Struct hierarchy</title>
51 * <link linkend="gi-GIBaseInfo">GIBaseInfo</link>
53 * +----<link linkend="gi-GIFunctionInfo">GIFunctionInfo</link>
54 * +----<link linkend="gi-GISignalInfo">GISignalInfo</link>
55 * +----<link linkend="gi-GIVFuncInfo">GIVFuncInfo</link>
61 signature_offset (GICallableInfo *info)
63 GIRealInfo *rinfo = (GIRealInfo*)info;
68 case GI_INFO_TYPE_FUNCTION:
69 sigoff = G_STRUCT_OFFSET (FunctionBlob, signature);
71 case GI_INFO_TYPE_VFUNC:
72 sigoff = G_STRUCT_OFFSET (VFuncBlob, signature);
74 case GI_INFO_TYPE_CALLBACK:
75 sigoff = G_STRUCT_OFFSET (CallbackBlob, signature);
77 case GI_INFO_TYPE_SIGNAL:
78 sigoff = G_STRUCT_OFFSET (SignalBlob, signature);
82 return *(guint32 *)&rinfo->typelib->data[rinfo->offset + sigoff];
87 * g_callable_info_can_throw_gerror:
88 * @info: a #GICallableInfo
93 * Returns: %TRUE if this #GICallableInfo can throw a #GError
96 g_callable_info_can_throw_gerror (GICallableInfo *info)
98 GIRealInfo *rinfo = (GIRealInfo*)info;
99 SignatureBlob *signature;
101 signature = (SignatureBlob *)&rinfo->typelib->data[signature_offset (info)];
102 if (signature->throws)
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.
110 switch (rinfo->type) {
111 case GI_INFO_TYPE_FUNCTION:
114 blob = (FunctionBlob *)&rinfo->typelib->data[rinfo->offset];
117 case GI_INFO_TYPE_VFUNC:
120 blob = (VFuncBlob *)&rinfo->typelib->data[rinfo->offset];
123 case GI_INFO_TYPE_CALLBACK:
124 case GI_INFO_TYPE_SIGNAL:
127 g_assert_not_reached ();
132 * g_callable_info_is_method:
133 * @info: a #GICallableInfo
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.
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"
145 * Returns: %TRUE if @info is a method, %FALSE otherwise
149 g_callable_info_is_method (GICallableInfo *info)
151 GIRealInfo *rinfo = (GIRealInfo*)info;
152 switch (rinfo->type) {
153 case GI_INFO_TYPE_FUNCTION:
156 blob = (FunctionBlob *)&rinfo->typelib->data[rinfo->offset];
157 return (!blob->constructor && !blob->is_static);
159 case GI_INFO_TYPE_VFUNC:
160 case GI_INFO_TYPE_SIGNAL:
162 case GI_INFO_TYPE_CALLBACK:
165 g_assert_not_reached ();
170 * g_callable_info_get_return_type:
171 * @info: a #GICallableInfo
173 * Obtain the return type of a callable item as a #GITypeInfo.
175 * Returns: (transfer full): the #GITypeInfo. Free the struct by calling
176 * g_base_info_unref() when done.
179 g_callable_info_get_return_type (GICallableInfo *info)
181 GIRealInfo *rinfo = (GIRealInfo *)info;
184 g_return_val_if_fail (info != NULL, NULL);
185 g_return_val_if_fail (GI_IS_CALLABLE_INFO (info), NULL);
187 offset = signature_offset (info);
189 return _g_type_info_new ((GIBaseInfo*)info, rinfo->typelib, offset);
194 * g_callable_info_load_return_type:
195 * @info: a #GICallableInfo
196 * @type: (out caller-allocates): Initialized with return type of @info
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
202 * The initialized @type must not be referenced after @info is deallocated.
205 g_callable_info_load_return_type (GICallableInfo *info,
208 GIRealInfo *rinfo = (GIRealInfo *)info;
211 g_return_if_fail (info != NULL);
212 g_return_if_fail (GI_IS_CALLABLE_INFO (info));
214 offset = signature_offset (info);
216 _g_type_info_init (type, (GIBaseInfo*)info, rinfo->typelib, offset);
220 * g_callable_info_may_return_null:
221 * @info: a #GICallableInfo
223 * See if a callable could return %NULL.
225 * Returns: %TRUE if callable could return %NULL
228 g_callable_info_may_return_null (GICallableInfo *info)
230 GIRealInfo *rinfo = (GIRealInfo *)info;
233 g_return_val_if_fail (info != NULL, FALSE);
234 g_return_val_if_fail (GI_IS_CALLABLE_INFO (info), FALSE);
236 blob = (SignatureBlob *)&rinfo->typelib->data[signature_offset (info)];
238 return blob->may_return_null;
242 * g_callable_info_skip_return:
243 * @info: a #GICallableInfo
245 * See if a callable's return value is only useful in C.
247 * Returns: %TRUE if return value is only useful in C.
250 g_callable_info_skip_return (GICallableInfo *info)
252 GIRealInfo *rinfo = (GIRealInfo *)info;
255 g_return_val_if_fail (info != NULL, FALSE);
256 g_return_val_if_fail (GI_IS_CALLABLE_INFO (info), FALSE);
258 blob = (SignatureBlob *)&rinfo->typelib->data[signature_offset (info)];
260 return blob->skip_return;
264 * g_callable_info_get_caller_owns:
265 * @info: a #GICallableInfo
267 * See whether the caller owns the return value of this callable.
268 * #GITransfer contains a list of possible transfer values.
270 * Returns: the transfer mode for the return value of the callable
273 g_callable_info_get_caller_owns (GICallableInfo *info)
275 GIRealInfo *rinfo = (GIRealInfo*) info;
278 g_return_val_if_fail (info != NULL, -1);
279 g_return_val_if_fail (GI_IS_CALLABLE_INFO (info), -1);
281 blob = (SignatureBlob *)&rinfo->typelib->data[signature_offset (info)];
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;
288 return GI_TRANSFER_NOTHING;
292 * g_callable_info_get_instance_ownership_transfer:
293 * @info: a #GICallableInfo
295 * Obtains the ownership transfer for the instance argument.
296 * #GITransfer contains a list of possible transfer values.
298 * Returns: the transfer mode of the instance argument
301 g_callable_info_get_instance_ownership_transfer (GICallableInfo *info)
303 GIRealInfo *rinfo = (GIRealInfo*) info;
306 g_return_val_if_fail (info != NULL, -1);
307 g_return_val_if_fail (GI_IS_CALLABLE_INFO (info), -1);
309 blob = (SignatureBlob *)&rinfo->typelib->data[signature_offset (info)];
311 if (blob->instance_transfer_ownership)
312 return GI_TRANSFER_EVERYTHING;
314 return GI_TRANSFER_NOTHING;
318 * g_callable_info_get_n_args:
319 * @info: a #GICallableInfo
321 * Obtain the number of arguments (both IN and OUT) for this callable.
323 * Returns: The number of arguments this callable expects.
326 g_callable_info_get_n_args (GICallableInfo *info)
328 GIRealInfo *rinfo = (GIRealInfo *)info;
332 g_return_val_if_fail (info != NULL, -1);
333 g_return_val_if_fail (GI_IS_CALLABLE_INFO (info), -1);
335 offset = signature_offset (info);
336 blob = (SignatureBlob *)&rinfo->typelib->data[offset];
338 return blob->n_arguments;
342 * g_callable_info_get_arg:
343 * @info: a #GICallableInfo
344 * @n: the argument index to fetch
346 * Obtain information about a particular argument of this callable.
348 * Returns: (transfer full): the #GIArgInfo. Free it with
349 * g_base_info_unref() when done.
352 g_callable_info_get_arg (GICallableInfo *info,
355 GIRealInfo *rinfo = (GIRealInfo *)info;
359 g_return_val_if_fail (info != NULL, NULL);
360 g_return_val_if_fail (GI_IS_CALLABLE_INFO (info), NULL);
362 offset = signature_offset (info);
363 header = (Header *)rinfo->typelib->data;
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);
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
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
379 * The initialized @arg must not be referenced after @info is deallocated.
382 g_callable_info_load_arg (GICallableInfo *info,
386 GIRealInfo *rinfo = (GIRealInfo *)info;
390 g_return_if_fail (info != NULL);
391 g_return_if_fail (GI_IS_CALLABLE_INFO (info));
393 offset = signature_offset (info);
394 header = (Header *)rinfo->typelib->data;
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);
401 * g_callable_info_get_return_attribute:
402 * @info: a #GICallableInfo
403 * @name: a freeform string naming an attribute
405 * Retrieve an arbitrary attribute associated with the return value.
407 * Returns: The value of the attribute, or %NULL if no such attribute exists
410 g_callable_info_get_return_attribute (GICallableInfo *info,
413 GIAttributeIter iter = { 0, };
414 gchar *curname, *curvalue;
415 while (g_callable_info_iterate_return_attributes (info, &iter, &curname, &curvalue))
417 if (g_strcmp0 (name, curname) == 0)
418 return (const gchar*) curvalue;
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
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.
435 * Both the @name and @value should be treated as constants
436 * and must not be freed.
438 * See g_base_info_iterate_attributes() for an example of how to use a
441 * Returns: %TRUE if there are more attributes
444 g_callable_info_iterate_return_attributes (GICallableInfo *info,
445 GIAttributeIter *iterator,
449 GIRealInfo *rinfo = (GIRealInfo *)info;
450 Header *header = (Header *)rinfo->typelib->data;
451 AttributeBlob *next, *after;
454 after = (AttributeBlob *) &rinfo->typelib->data[header->attributes +
455 header->n_attributes * header->attribute_blob_size];
457 blob_offset = signature_offset (info);
459 if (iterator->data != NULL)
460 next = (AttributeBlob *) iterator->data;
462 next = _attribute_blob_find_first (info, blob_offset);
464 if (next == NULL || next->offset != blob_offset || next >= after)
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;
475 * gi_type_info_extract_ffi_return_value:
478 * @arg: (out caller-allocates): TODO
480 * Extract the correct bits from an ffi_arg return value into
481 * GIArgument: https://bugzilla.gnome.org/show_bug.cgi?id=665152
483 * Also see <citerefentry><refentrytitle>ffi_call</refentrytitle><manvolnum>3</manvolnum></citerefentry>
484 * - the storage requirements for return values are "special".
487 gi_type_info_extract_ffi_return_value (GITypeInfo *return_info,
488 GIFFIReturnValue *ffi_value,
491 switch (g_type_info_get_tag (return_info)) {
492 case GI_TYPE_TAG_INT8:
493 arg->v_int8 = (gint8) ffi_value->v_long;
495 case GI_TYPE_TAG_UINT8:
496 arg->v_uint8 = (guint8) ffi_value->v_ulong;
498 case GI_TYPE_TAG_INT16:
499 arg->v_int16 = (gint16) ffi_value->v_long;
501 case GI_TYPE_TAG_UINT16:
502 arg->v_uint16 = (guint16) ffi_value->v_ulong;
504 case GI_TYPE_TAG_INT32:
505 arg->v_int32 = (gint32) ffi_value->v_long;
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;
512 case GI_TYPE_TAG_INT64:
513 arg->v_int64 = (gint64) ffi_value->v_int64;
515 case GI_TYPE_TAG_UINT64:
516 arg->v_uint64 = (guint64) ffi_value->v_uint64;
518 case GI_TYPE_TAG_FLOAT:
519 arg->v_float = ffi_value->v_float;
521 case GI_TYPE_TAG_DOUBLE:
522 arg->v_double = ffi_value->v_double;
524 case GI_TYPE_TAG_INTERFACE:
526 GIBaseInfo* interface_info;
527 GIInfoType interface_type;
529 interface_info = g_type_info_get_interface(return_info);
530 interface_type = g_base_info_get_type(interface_info);
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;
538 arg->v_pointer = (gpointer) ffi_value->v_ulong;
542 g_base_info_unref(interface_info);
546 arg->v_pointer = (gpointer) ffi_value->v_ulong;
552 * g_callable_info_invoke:
559 * @return_value: TODO
567 g_callable_info_invoke (GIFunctionInfo *info,
569 const GIArgument *in_args,
571 const GIArgument *out_args,
573 GIArgument *return_value,
585 gint n_args, n_invoke_args, in_pos, out_pos, i;
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 */
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);
600 n_args = g_callable_info_get_n_args ((GICallableInfo *)info);
607 G_INVOKE_ERROR_ARGUMENT_MISMATCH,
608 "Too few \"in\" arguments (handling this)");
611 n_invoke_args = n_args+1;
615 n_invoke_args = n_args;
618 /* Add an argument for the GError */
621 atypes = g_alloca (sizeof (ffi_type*) * n_invoke_args);
622 args = g_alloca (sizeof (gpointer) * n_invoke_args);
626 atypes[0] = &ffi_type_pointer;
627 args[0] = (gpointer) &in_args[0];
629 for (i = 0; i < n_args; i++)
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))
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);
640 if (in_pos >= n_in_args)
644 G_INVOKE_ERROR_ARGUMENT_MISMATCH,
645 "Too few \"in\" arguments (handling in)");
649 args[i+offset] = (gpointer)&in_args[in_pos];
653 case GI_DIRECTION_OUT:
654 atypes[i+offset] = &ffi_type_pointer;
656 if (out_pos >= n_out_args)
660 G_INVOKE_ERROR_ARGUMENT_MISMATCH,
661 "Too few \"out\" arguments (handling out)");
665 args[i+offset] = (gpointer)&out_args[out_pos];
668 case GI_DIRECTION_INOUT:
669 atypes[i+offset] = &ffi_type_pointer;
671 if (in_pos >= n_in_args)
675 G_INVOKE_ERROR_ARGUMENT_MISMATCH,
676 "Too few \"in\" arguments (handling inout)");
680 if (out_pos >= n_out_args)
684 G_INVOKE_ERROR_ARGUMENT_MISMATCH,
685 "Too few \"out\" arguments (handling inout)");
689 args[i+offset] = (gpointer)&in_args[in_pos];
694 g_assert_not_reached ();
696 g_base_info_unref ((GIBaseInfo *)ainfo);
701 args[n_invoke_args - 1] = &error_address;
702 atypes[n_invoke_args - 1] = &ffi_type_pointer;
705 if (in_pos < n_in_args)
709 G_INVOKE_ERROR_ARGUMENT_MISMATCH,
710 "Too many \"in\" arguments (at end)");
713 if (out_pos < n_out_args)
717 G_INVOKE_ERROR_ARGUMENT_MISMATCH,
718 "Too many \"out\" arguments (at end)");
722 if (ffi_prep_cif (&cif, FFI_DEFAULT_ABI, n_invoke_args, rtype, atypes) != FFI_OK)
725 g_return_val_if_fail (return_value, FALSE);
726 /* See comment for GIFFIReturnValue above */
729 case GI_TYPE_TAG_FLOAT:
730 return_value_p = &ffi_return_value.v_float;
732 case GI_TYPE_TAG_DOUBLE:
733 return_value_p = &ffi_return_value.v_double;
735 case GI_TYPE_TAG_INT64:
736 case GI_TYPE_TAG_UINT64:
737 return_value_p = &ffi_return_value.v_uint64;
740 return_value_p = &ffi_return_value.v_long;
742 ffi_call (&cif, function, return_value_p, args);
746 g_propagate_error (error, local_error);
751 gi_type_info_extract_ffi_return_value (rinfo, &ffi_return_value, return_value);
755 g_base_info_unref ((GIBaseInfo *)rinfo);