mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-11-10 19:36:18 +01:00
e4332bc78d
Signed-off-by: Philip Withnall <pwithnall@gnome.org> Helps: #3155
306 lines
9.0 KiB
C
306 lines
9.0 KiB
C
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
|
* GObject introspection: Function implementation
|
|
*
|
|
* Copyright (C) 2005 Matthias Clasen
|
|
* Copyright (C) 2008,2009 Red Hat, Inc.
|
|
*
|
|
* SPDX-License-Identifier: LGPL-2.1-or-later
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
* Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <string.h>
|
|
|
|
#include <glib.h>
|
|
|
|
#include <girepository/girepository.h>
|
|
#include "gibaseinfo-private.h"
|
|
#include "girepository-private.h"
|
|
#include "gitypelib-internal.h"
|
|
#include "gifunctioninfo.h"
|
|
|
|
/**
|
|
* SECTION:gifunctioninfo
|
|
* @title: GIFunctionInfo
|
|
* @short_description: Struct representing a function
|
|
*
|
|
* GIFunctionInfo represents a function, method or constructor.
|
|
*
|
|
* To find out what kind of entity a #GIFunctionInfo represents, call
|
|
* gi_function_info_get_flags().
|
|
*
|
|
* See also #GICallableInfo for information on how to retreive arguments and
|
|
* other metadata.
|
|
*/
|
|
|
|
GIFunctionInfo *
|
|
gi_base_info_find_method (GIBaseInfo *base,
|
|
guint32 offset,
|
|
guint n_methods,
|
|
const gchar *name)
|
|
{
|
|
/* FIXME hash */
|
|
GIRealInfo *rinfo = (GIRealInfo*)base;
|
|
Header *header = (Header *)rinfo->typelib->data;
|
|
|
|
for (guint i = 0; i < n_methods; i++)
|
|
{
|
|
FunctionBlob *fblob = (FunctionBlob *)&rinfo->typelib->data[offset];
|
|
const gchar *fname = (const gchar *)&rinfo->typelib->data[fblob->name];
|
|
|
|
if (strcmp (name, fname) == 0)
|
|
return (GIFunctionInfo *) gi_info_new (GI_INFO_TYPE_FUNCTION, base,
|
|
rinfo->typelib, offset);
|
|
|
|
offset += header->function_blob_size;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* gi_function_info_get_symbol:
|
|
* @info: a #GIFunctionInfo
|
|
*
|
|
* Obtain the symbol of the function. The symbol is the name of the
|
|
* exported function, suitable to be used as an argument to
|
|
* g_module_symbol().
|
|
*
|
|
* Returns: the symbol
|
|
*/
|
|
const gchar *
|
|
gi_function_info_get_symbol (GIFunctionInfo *info)
|
|
{
|
|
GIRealInfo *rinfo;
|
|
FunctionBlob *blob;
|
|
|
|
g_return_val_if_fail (info != NULL, NULL);
|
|
g_return_val_if_fail (GI_IS_FUNCTION_INFO (info), NULL);
|
|
|
|
rinfo = (GIRealInfo *)info;
|
|
blob = (FunctionBlob *)&rinfo->typelib->data[rinfo->offset];
|
|
|
|
return gi_typelib_get_string (rinfo->typelib, blob->symbol);
|
|
}
|
|
|
|
/**
|
|
* gi_function_info_get_flags:
|
|
* @info: a #GIFunctionInfo
|
|
*
|
|
* Obtain the #GIFunctionInfoFlags for the @info.
|
|
*
|
|
* Returns: the flags
|
|
*/
|
|
GIFunctionInfoFlags
|
|
gi_function_info_get_flags (GIFunctionInfo *info)
|
|
{
|
|
GIFunctionInfoFlags flags;
|
|
GIRealInfo *rinfo;
|
|
FunctionBlob *blob;
|
|
|
|
g_return_val_if_fail (info != NULL, -1);
|
|
g_return_val_if_fail (GI_IS_FUNCTION_INFO (info), -1);
|
|
|
|
rinfo = (GIRealInfo *)info;
|
|
blob = (FunctionBlob *)&rinfo->typelib->data[rinfo->offset];
|
|
|
|
flags = 0;
|
|
|
|
/* Make sure we don't flag Constructors as methods */
|
|
if (!blob->constructor && !blob->is_static)
|
|
flags = flags | GI_FUNCTION_IS_METHOD;
|
|
|
|
if (blob->constructor)
|
|
flags = flags | GI_FUNCTION_IS_CONSTRUCTOR;
|
|
|
|
if (blob->getter)
|
|
flags = flags | GI_FUNCTION_IS_GETTER;
|
|
|
|
if (blob->setter)
|
|
flags = flags | GI_FUNCTION_IS_SETTER;
|
|
|
|
if (blob->wraps_vfunc)
|
|
flags = flags | GI_FUNCTION_WRAPS_VFUNC;
|
|
|
|
if (blob->throws)
|
|
flags = flags | GI_FUNCTION_THROWS;
|
|
|
|
return flags;
|
|
}
|
|
|
|
/**
|
|
* gi_function_info_get_property:
|
|
* @info: a #GIFunctionInfo
|
|
*
|
|
* Obtain the property associated with this #GIFunctionInfo.
|
|
* Only #GIFunctionInfo with the flag %GI_FUNCTION_IS_GETTER or
|
|
* %GI_FUNCTION_IS_SETTER have a property set. For other cases,
|
|
* %NULL will be returned.
|
|
*
|
|
* Returns: (transfer full): the property or %NULL if not set. Free it with
|
|
* gi_base_info_unref() when done.
|
|
*/
|
|
GIPropertyInfo *
|
|
gi_function_info_get_property (GIFunctionInfo *info)
|
|
{
|
|
GIRealInfo *rinfo;
|
|
FunctionBlob *blob;
|
|
|
|
g_return_val_if_fail (info != NULL, NULL);
|
|
g_return_val_if_fail (GI_IS_FUNCTION_INFO (info), NULL);
|
|
|
|
rinfo = (GIRealInfo *)info;
|
|
blob = (FunctionBlob *)&rinfo->typelib->data[rinfo->offset];
|
|
|
|
if (gi_base_info_get_info_type ((GIBaseInfo *) rinfo->container) == GI_INFO_TYPE_INTERFACE)
|
|
{
|
|
GIInterfaceInfo *container = (GIInterfaceInfo *)rinfo->container;
|
|
|
|
return gi_interface_info_get_property (container, blob->index);
|
|
}
|
|
else if (gi_base_info_get_info_type ((GIBaseInfo *) rinfo->container) == GI_INFO_TYPE_OBJECT)
|
|
{
|
|
GIObjectInfo *container = (GIObjectInfo *)rinfo->container;
|
|
|
|
return gi_object_info_get_property (container, blob->index);
|
|
}
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* gi_function_info_get_vfunc:
|
|
* @info: a #GIFunctionInfo
|
|
*
|
|
* Obtain the virtual function associated with this #GIFunctionInfo.
|
|
* Only #GIFunctionInfo with the flag %GI_FUNCTION_WRAPS_VFUNC has
|
|
* a virtual function set. For other cases, %NULL will be returned.
|
|
*
|
|
* Returns: (transfer full): the virtual function or %NULL if not set.
|
|
* Free it by calling gi_base_info_unref() when done.
|
|
*/
|
|
GIVFuncInfo *
|
|
gi_function_info_get_vfunc (GIFunctionInfo *info)
|
|
{
|
|
GIRealInfo *rinfo;
|
|
FunctionBlob *blob;
|
|
GIInterfaceInfo *container;
|
|
|
|
g_return_val_if_fail (info != NULL, NULL);
|
|
g_return_val_if_fail (GI_IS_FUNCTION_INFO (info), NULL);
|
|
|
|
rinfo = (GIRealInfo *)info;
|
|
blob = (FunctionBlob *)&rinfo->typelib->data[rinfo->offset];
|
|
container = (GIInterfaceInfo *)rinfo->container;
|
|
|
|
return gi_interface_info_get_vfunc (container, blob->index);
|
|
}
|
|
|
|
/**
|
|
* gi_invoke_error_quark:
|
|
*
|
|
* TODO
|
|
*
|
|
* Returns: TODO
|
|
*/
|
|
GQuark
|
|
gi_invoke_error_quark (void)
|
|
{
|
|
static GQuark quark = 0;
|
|
if (quark == 0)
|
|
quark = g_quark_from_static_string ("gi-invoke-error-quark");
|
|
return quark;
|
|
}
|
|
|
|
/**
|
|
* gi_function_info_invoke: (skip)
|
|
* @info: a #GIFunctionInfo describing the function to invoke
|
|
* @in_args: (array length=n_in_args): an array of #GIArgument<!-- -->s, one for each in
|
|
* parameter of @info. If there are no in parameter, @in_args
|
|
* can be %NULL
|
|
* @n_in_args: the length of the @in_args array
|
|
* @out_args: (array length=n_out_args): an array of #GIArgument<!-- -->s, one for each out
|
|
* parameter of @info. If there are no out parameters, @out_args
|
|
* may be %NULL
|
|
* @n_out_args: the length of the @out_args array
|
|
* @return_value: return location for the return value of the
|
|
* function.
|
|
* @error: return location for detailed error information, or %NULL
|
|
*
|
|
* Invokes the function described in @info with the given
|
|
* arguments. Note that inout parameters must appear in both
|
|
* argument lists. This function uses dlsym() to obtain a pointer
|
|
* to the function, so the library or shared object containing the
|
|
* described function must either be linked to the caller, or must
|
|
* have been g_module_symbol()<!-- -->ed before calling this function.
|
|
*
|
|
* Returns: %TRUE if the function has been invoked, %FALSE if an
|
|
* error occurred.
|
|
*/
|
|
gboolean
|
|
gi_function_info_invoke (GIFunctionInfo *info,
|
|
const GIArgument *in_args,
|
|
gsize n_in_args,
|
|
const GIArgument *out_args,
|
|
gsize n_out_args,
|
|
GIArgument *return_value,
|
|
GError **error)
|
|
{
|
|
const gchar *symbol;
|
|
gpointer func;
|
|
gboolean is_method;
|
|
gboolean throws;
|
|
|
|
symbol = gi_function_info_get_symbol (info);
|
|
|
|
if (!gi_typelib_symbol (gi_base_info_get_typelib ((GIBaseInfo *) info),
|
|
symbol, &func))
|
|
{
|
|
g_set_error (error,
|
|
GI_INVOKE_ERROR,
|
|
GI_INVOKE_ERROR_SYMBOL_NOT_FOUND,
|
|
"Could not locate %s: %s", symbol, g_module_error ());
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
is_method = (gi_function_info_get_flags (info) & GI_FUNCTION_IS_METHOD) != 0
|
|
&& (gi_function_info_get_flags (info) & GI_FUNCTION_IS_CONSTRUCTOR) == 0;
|
|
throws = gi_function_info_get_flags (info) & GI_FUNCTION_THROWS;
|
|
|
|
return gi_callable_info_invoke ((GICallableInfo*) info,
|
|
func,
|
|
in_args,
|
|
n_in_args,
|
|
out_args,
|
|
n_out_args,
|
|
return_value,
|
|
is_method,
|
|
throws,
|
|
error);
|
|
}
|
|
|
|
void
|
|
gi_function_info_class_init (gpointer g_class,
|
|
gpointer class_data)
|
|
{
|
|
GIBaseInfoClass *info_class = g_class;
|
|
|
|
info_class->info_type = GI_INFO_TYPE_FUNCTION;
|
|
}
|