(root)/
glib-2.79.0/
girepository/
gifunctioninfo.c
       1  /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
       2   * GObject introspection: Function implementation
       3   *
       4   * Copyright (C) 2005 Matthias Clasen
       5   * Copyright (C) 2008,2009 Red Hat, Inc.
       6   *
       7   * SPDX-License-Identifier: LGPL-2.1-or-later
       8   *
       9   * This library is free software; you can redistribute it and/or
      10   * modify it under the terms of the GNU Lesser General Public
      11   * License as published by the Free Software Foundation; either
      12   * version 2 of the License, or (at your option) any later version.
      13   *
      14   * This library is distributed in the hope that it will be useful,
      15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      17   * Lesser General Public License for more details.
      18   *
      19   * You should have received a copy of the GNU Lesser General Public
      20   * License along with this library; if not, write to the
      21   * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      22   * Boston, MA 02111-1307, USA.
      23   */
      24  
      25  #include "config.h"
      26  
      27  #include <string.h>
      28  
      29  #include <glib.h>
      30  
      31  #include <girepository/girepository.h>
      32  #include "gibaseinfo-private.h"
      33  #include "girepository-private.h"
      34  #include "gitypelib-internal.h"
      35  #include "gifunctioninfo.h"
      36  
      37  /**
      38   * GIFunctionInfo:
      39   *
      40   * `GIFunctionInfo` represents a function, method or constructor.
      41   *
      42   * To find out what kind of entity a `GIFunctionInfo` represents, call
      43   * [method@GIRepository.FunctionInfo.get_flags].
      44   *
      45   * See also [class@GIRepository.CallableInfo] for information on how to retrieve
      46   * arguments and other metadata.
      47   *
      48   * Since: 2.80
      49   */
      50  
      51  GIFunctionInfo *
      52  gi_base_info_find_method (GIBaseInfo  *base,
      53                            guint32      offset,
      54                            guint        n_methods,
      55                            const gchar *name)
      56  {
      57    /* FIXME hash */
      58    GIRealInfo *rinfo = (GIRealInfo*)base;
      59    Header *header = (Header *)rinfo->typelib->data;
      60  
      61    for (guint i = 0; i < n_methods; i++)
      62      {
      63        FunctionBlob *fblob = (FunctionBlob *)&rinfo->typelib->data[offset];
      64        const gchar *fname = (const gchar *)&rinfo->typelib->data[fblob->name];
      65  
      66        if (strcmp (name, fname) == 0)
      67          return (GIFunctionInfo *) gi_info_new (GI_INFO_TYPE_FUNCTION, base,
      68                                                 rinfo->typelib, offset);
      69  
      70        offset += header->function_blob_size;
      71      }
      72  
      73    return NULL;
      74  }
      75  
      76  /**
      77   * gi_function_info_get_symbol:
      78   * @info: a #GIFunctionInfo
      79   *
      80   * Obtain the symbol of the function.
      81   *
      82   * The symbol is the name of the exported function, suitable to be used as an
      83   * argument to [method@GModule.Module.symbol].
      84   *
      85   * Returns: the symbol
      86   * Since: 2.80
      87   */
      88  const gchar *
      89  gi_function_info_get_symbol (GIFunctionInfo *info)
      90  {
      91    GIRealInfo *rinfo;
      92    FunctionBlob *blob;
      93  
      94    g_return_val_if_fail (info != NULL, NULL);
      95    g_return_val_if_fail (GI_IS_FUNCTION_INFO (info), NULL);
      96  
      97    rinfo = (GIRealInfo *)info;
      98    blob = (FunctionBlob *)&rinfo->typelib->data[rinfo->offset];
      99  
     100    return gi_typelib_get_string (rinfo->typelib, blob->symbol);
     101  }
     102  
     103  /**
     104   * gi_function_info_get_flags:
     105   * @info: a #GIFunctionInfo
     106   *
     107   * Obtain the [type@GIRepository.FunctionInfoFlags] for the @info.
     108   *
     109   * Returns: the flags
     110   * Since: 2.80
     111   */
     112  GIFunctionInfoFlags
     113  gi_function_info_get_flags (GIFunctionInfo *info)
     114  {
     115    GIFunctionInfoFlags flags;
     116    GIRealInfo *rinfo;
     117    FunctionBlob *blob;
     118  
     119    g_return_val_if_fail (info != NULL, -1);
     120    g_return_val_if_fail (GI_IS_FUNCTION_INFO (info), -1);
     121  
     122    rinfo = (GIRealInfo *)info;
     123    blob = (FunctionBlob *)&rinfo->typelib->data[rinfo->offset];
     124  
     125    flags = 0;
     126  
     127    /* Make sure we don't flag Constructors as methods */
     128    if (!blob->constructor && !blob->is_static)
     129      flags = flags | GI_FUNCTION_IS_METHOD;
     130  
     131    if (blob->constructor)
     132      flags = flags | GI_FUNCTION_IS_CONSTRUCTOR;
     133  
     134    if (blob->getter)
     135      flags = flags | GI_FUNCTION_IS_GETTER;
     136  
     137    if (blob->setter)
     138      flags = flags | GI_FUNCTION_IS_SETTER;
     139  
     140    if (blob->wraps_vfunc)
     141      flags = flags | GI_FUNCTION_WRAPS_VFUNC;
     142  
     143    if (blob->throws)
     144      flags = flags | GI_FUNCTION_THROWS;
     145  
     146    return flags;
     147  }
     148  
     149  /**
     150   * gi_function_info_get_property:
     151   * @info: a #GIFunctionInfo
     152   *
     153   * Obtain the property associated with this `GIFunctionInfo`.
     154   *
     155   * Only `GIFunctionInfo`s with the flag `GI_FUNCTION_IS_GETTER` or
     156   * `GI_FUNCTION_IS_SETTER` have a property set. For other cases,
     157   * `NULL` will be returned.
     158   *
     159   * Returns: (transfer full) (nullable): The property or `NULL` if not set. Free
     160   *   it with [method@GIRepository.BaseInfo.unref] when done.
     161   * Since: 2.80
     162   */
     163  GIPropertyInfo *
     164  gi_function_info_get_property (GIFunctionInfo *info)
     165  {
     166    GIRealInfo *rinfo;
     167    FunctionBlob *blob;
     168  
     169    g_return_val_if_fail (info != NULL, NULL);
     170    g_return_val_if_fail (GI_IS_FUNCTION_INFO (info), NULL);
     171  
     172    rinfo = (GIRealInfo *)info;
     173    blob = (FunctionBlob *)&rinfo->typelib->data[rinfo->offset];
     174  
     175    if (gi_base_info_get_info_type ((GIBaseInfo *) rinfo->container) == GI_INFO_TYPE_INTERFACE)
     176      {
     177        GIInterfaceInfo *container = (GIInterfaceInfo *)rinfo->container;
     178  
     179        return gi_interface_info_get_property (container, blob->index);
     180      }
     181    else if (gi_base_info_get_info_type ((GIBaseInfo *) rinfo->container) == GI_INFO_TYPE_OBJECT)
     182      {
     183        GIObjectInfo *container = (GIObjectInfo *)rinfo->container;
     184  
     185        return gi_object_info_get_property (container, blob->index);
     186      }
     187    else
     188      return NULL;
     189  }
     190  
     191  /**
     192   * gi_function_info_get_vfunc:
     193   * @info: a #GIFunctionInfo
     194   *
     195   * Obtain the virtual function associated with this `GIFunctionInfo`.
     196   *
     197   * Only `GIFunctionInfo`s with the flag `GI_FUNCTION_WRAPS_VFUNC` have
     198   * a virtual function set. For other cases, `NULL` will be returned.
     199   *
     200   * Returns: (transfer full) (nullable): The virtual function or `NULL` if not
     201   *   set. Free it by calling [method@GIRepository.BaseInfo.unref] when done.
     202   * Since: 2.80
     203   */
     204  GIVFuncInfo *
     205  gi_function_info_get_vfunc (GIFunctionInfo *info)
     206  {
     207    GIRealInfo *rinfo;
     208    FunctionBlob *blob;
     209    GIInterfaceInfo *container;
     210  
     211    g_return_val_if_fail (info != NULL, NULL);
     212    g_return_val_if_fail (GI_IS_FUNCTION_INFO (info), NULL);
     213  
     214    rinfo = (GIRealInfo *)info;
     215    blob = (FunctionBlob *)&rinfo->typelib->data[rinfo->offset];
     216    container = (GIInterfaceInfo *)rinfo->container;
     217  
     218    return gi_interface_info_get_vfunc (container, blob->index);
     219  }
     220  
     221  /**
     222   * gi_invoke_error_quark:
     223   *
     224   * Get the error quark which represents [type@GIRepository.InvokeError].
     225   *
     226   * Returns: error quark
     227   * Since: 2.80
     228   */
     229  GQuark
     230  gi_invoke_error_quark (void)
     231  {
     232    static GQuark quark = 0;
     233    if (quark == 0)
     234      quark = g_quark_from_static_string ("gi-invoke-error-quark");
     235    return quark;
     236  }
     237  
     238  /**
     239   * gi_function_info_invoke: (skip)
     240   * @info: a #GIFunctionInfo describing the function to invoke
     241   * @in_args: (array length=n_in_args) (nullable): An array of
     242   *   [type@GIRepository.Argument]s, one for each ‘in’ parameter of @info. If
     243   *   there are no ‘in’ parameters, @in_args can be `NULL`.
     244   * @n_in_args: the length of the @in_args array
     245   * @out_args: (array length=n_out_args) (nullable): An array of
     246   *   [type@GIRepository.Argument]s, one for each ‘out’ parameter of @info. If
     247   *   there are no ‘out’ parameters, @out_args may be `NULL`.
     248   * @n_out_args: the length of the @out_args array
     249   * @return_value: (out caller-allocates) (not optional): return location for the
     250   *   return value of the function.
     251   * @error: return location for detailed error information, or `NULL`
     252   *
     253   * Invokes the function described in @info with the given
     254   * arguments.
     255   *
     256   * Note that ‘inout’ parameters must appear in both argument lists. This
     257   * function uses [`dlsym()`](man:dlsym(3)) to obtain a pointer to the function,
     258   * so the library or shared object containing the described function must either
     259   * be linked to the caller, or must have been loaded with
     260   * [method@GModule.Module.symbol] before calling this function.
     261   *
     262   * Returns: `TRUE` if the function has been invoked, `FALSE` if an
     263   *   error occurred.
     264   * Since: 2.80
     265   */
     266  gboolean
     267  gi_function_info_invoke (GIFunctionInfo    *info,
     268                           const GIArgument  *in_args,
     269                           gsize              n_in_args,
     270                           const GIArgument  *out_args,
     271                           gsize              n_out_args,
     272                           GIArgument        *return_value,
     273                           GError           **error)
     274  {
     275    const gchar *symbol;
     276    gpointer func;
     277    gboolean is_method;
     278    gboolean throws;
     279  
     280    symbol = gi_function_info_get_symbol (info);
     281  
     282    if (!gi_typelib_symbol (gi_base_info_get_typelib ((GIBaseInfo *) info),
     283                            symbol, &func))
     284      {
     285        g_set_error (error,
     286                     GI_INVOKE_ERROR,
     287                     GI_INVOKE_ERROR_SYMBOL_NOT_FOUND,
     288                     "Could not locate %s: %s", symbol, g_module_error ());
     289  
     290        return FALSE;
     291      }
     292  
     293    is_method = (gi_function_info_get_flags (info) & GI_FUNCTION_IS_METHOD) != 0
     294      && (gi_function_info_get_flags (info) & GI_FUNCTION_IS_CONSTRUCTOR) == 0;
     295    throws = gi_function_info_get_flags (info) & GI_FUNCTION_THROWS;
     296  
     297    return gi_callable_info_invoke ((GICallableInfo*) info,
     298                                    func,
     299                                    in_args,
     300                                    n_in_args,
     301                                    out_args,
     302                                    n_out_args,
     303                                    return_value,
     304                                    is_method,
     305                                    throws,
     306                                    error);
     307  }
     308  
     309  void
     310  gi_function_info_class_init (gpointer g_class,
     311                               gpointer class_data)
     312  {
     313    GIBaseInfoClass *info_class = g_class;
     314  
     315    info_class->info_type = GI_INFO_TYPE_FUNCTION;
     316  }