Branch data Line data Source code
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 : 24 : gi_base_info_find_method (GIBaseInfo *base,
53 : : uint32_t offset,
54 : : uint16_t n_methods,
55 : : const char *name)
56 : : {
57 : : /* FIXME hash */
58 : 24 : GIRealInfo *rinfo = (GIRealInfo*)base;
59 : 24 : Header *header = (Header *)rinfo->typelib->data;
60 : :
61 : 363 : for (uint16_t i = 0; i < n_methods; i++)
62 : : {
63 : 359 : FunctionBlob *fblob = (FunctionBlob *)&rinfo->typelib->data[offset];
64 : 359 : const char *fname = (const char *)&rinfo->typelib->data[fblob->name];
65 : :
66 : 359 : if (strcmp (name, fname) == 0)
67 : 20 : return (GIFunctionInfo *) gi_base_info_new (GI_INFO_TYPE_FUNCTION, base,
68 : : rinfo->typelib, offset);
69 : :
70 : 339 : offset += header->function_blob_size;
71 : : }
72 : :
73 : 4 : 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 char *
89 : 5 : gi_function_info_get_symbol (GIFunctionInfo *info)
90 : : {
91 : : GIRealInfo *rinfo;
92 : : FunctionBlob *blob;
93 : :
94 : 5 : g_return_val_if_fail (info != NULL, NULL);
95 : 5 : g_return_val_if_fail (GI_IS_FUNCTION_INFO (info), NULL);
96 : :
97 : 5 : rinfo = (GIRealInfo *)info;
98 : 5 : blob = (FunctionBlob *)&rinfo->typelib->data[rinfo->offset];
99 : :
100 : 5 : 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 : 2 : gi_function_info_get_flags (GIFunctionInfo *info)
114 : : {
115 : : GIFunctionInfoFlags flags;
116 : : GIRealInfo *rinfo;
117 : : FunctionBlob *blob;
118 : :
119 : 2 : g_return_val_if_fail (info != NULL, -1);
120 : 2 : g_return_val_if_fail (GI_IS_FUNCTION_INFO (info), -1);
121 : :
122 : 2 : rinfo = (GIRealInfo *)info;
123 : 2 : blob = (FunctionBlob *)&rinfo->typelib->data[rinfo->offset];
124 : :
125 : 2 : flags = 0;
126 : :
127 : : /* Make sure we don't flag Constructors as methods */
128 : 2 : if (!blob->constructor && !blob->is_static)
129 : 0 : flags = flags | GI_FUNCTION_IS_METHOD;
130 : :
131 : 2 : if (blob->constructor)
132 : 0 : flags = flags | GI_FUNCTION_IS_CONSTRUCTOR;
133 : :
134 : 2 : if (blob->getter)
135 : 0 : flags = flags | GI_FUNCTION_IS_GETTER;
136 : :
137 : 2 : if (blob->setter)
138 : 0 : flags = flags | GI_FUNCTION_IS_SETTER;
139 : :
140 : 2 : if (blob->wraps_vfunc)
141 : 0 : flags = flags | GI_FUNCTION_WRAPS_VFUNC;
142 : :
143 : 2 : if (blob->is_async)
144 : 0 : flags = flags | GI_FUNCTION_IS_ASYNC;
145 : :
146 : 2 : 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 : 0 : gi_function_info_get_property (GIFunctionInfo *info)
165 : : {
166 : : GIRealInfo *rinfo;
167 : : FunctionBlob *blob;
168 : :
169 : 0 : g_return_val_if_fail (info != NULL, NULL);
170 : 0 : g_return_val_if_fail (GI_IS_FUNCTION_INFO (info), NULL);
171 : :
172 : 0 : rinfo = (GIRealInfo *)info;
173 : 0 : blob = (FunctionBlob *)&rinfo->typelib->data[rinfo->offset];
174 : :
175 : 0 : if (gi_base_info_get_info_type ((GIBaseInfo *) rinfo->container) == GI_INFO_TYPE_INTERFACE)
176 : : {
177 : 0 : GIInterfaceInfo *container = (GIInterfaceInfo *)rinfo->container;
178 : :
179 : 0 : return gi_interface_info_get_property (container, blob->index);
180 : : }
181 : 0 : else if (gi_base_info_get_info_type ((GIBaseInfo *) rinfo->container) == GI_INFO_TYPE_OBJECT)
182 : : {
183 : 0 : GIObjectInfo *container = (GIObjectInfo *)rinfo->container;
184 : :
185 : 0 : return gi_object_info_get_property (container, blob->index);
186 : : }
187 : : else
188 : 0 : 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 : 0 : gi_function_info_get_vfunc (GIFunctionInfo *info)
206 : : {
207 : : GIRealInfo *rinfo;
208 : : FunctionBlob *blob;
209 : : GIInterfaceInfo *container;
210 : :
211 : 0 : g_return_val_if_fail (info != NULL, NULL);
212 : 0 : g_return_val_if_fail (GI_IS_FUNCTION_INFO (info), NULL);
213 : :
214 : 0 : rinfo = (GIRealInfo *)info;
215 : 0 : blob = (FunctionBlob *)&rinfo->typelib->data[rinfo->offset];
216 : 0 : container = (GIInterfaceInfo *)rinfo->container;
217 : :
218 : 0 : 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 : 1 : gi_invoke_error_quark (void)
231 : : {
232 : : static GQuark quark = 0;
233 : 1 : if (quark == 0)
234 : 1 : quark = g_quark_from_static_string ("gi-invoke-error-quark");
235 : 1 : 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 : 1 : gi_function_info_invoke (GIFunctionInfo *info,
268 : : const GIArgument *in_args,
269 : : size_t n_in_args,
270 : : GIArgument *out_args,
271 : : size_t n_out_args,
272 : : GIArgument *return_value,
273 : : GError **error)
274 : : {
275 : : const char *symbol;
276 : : void *func;
277 : :
278 : 1 : symbol = gi_function_info_get_symbol (info);
279 : :
280 : 1 : if (!gi_typelib_symbol (gi_base_info_get_typelib ((GIBaseInfo *) info),
281 : : symbol, &func))
282 : : {
283 : 0 : g_set_error (error,
284 : : GI_INVOKE_ERROR,
285 : : GI_INVOKE_ERROR_SYMBOL_NOT_FOUND,
286 : : "Could not locate %s: %s", symbol, g_module_error ());
287 : :
288 : 0 : return FALSE;
289 : : }
290 : :
291 : 1 : return gi_callable_info_invoke ((GICallableInfo*) info,
292 : : func,
293 : : in_args,
294 : : n_in_args,
295 : : out_args,
296 : : n_out_args,
297 : : return_value,
298 : : error);
299 : : }
300 : :
301 : : void
302 : 8 : gi_function_info_class_init (gpointer g_class,
303 : : gpointer class_data)
304 : : {
305 : 8 : GIBaseInfoClass *info_class = g_class;
306 : :
307 : 8 : info_class->info_type = GI_INFO_TYPE_FUNCTION;
308 : 8 : }
|