gobject-introspection 3.3.8 → 3.3.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/ext/gobject-introspection/extconf.rb +4 -4
  3. data/ext/gobject-introspection/gobject_introspection.def +2 -1
  4. data/ext/gobject-introspection/rb-gi-arg-info.c +33 -1
  5. data/ext/gobject-introspection/rb-gi-argument.c +384 -3291
  6. data/ext/gobject-introspection/rb-gi-arguments-in.c +2229 -0
  7. data/ext/gobject-introspection/rb-gi-arguments-out.c +929 -0
  8. data/ext/gobject-introspection/rb-gi-arguments.c +850 -0
  9. data/ext/gobject-introspection/rb-gi-array-type.c +54 -0
  10. data/ext/gobject-introspection/rb-gi-callback.c +242 -0
  11. data/ext/gobject-introspection/rb-gi-conversions.h +0 -43
  12. data/ext/gobject-introspection/rb-gi-direction.c +36 -0
  13. data/ext/gobject-introspection/rb-gi-field-info.c +172 -81
  14. data/ext/gobject-introspection/rb-gi-function-info.c +15 -1404
  15. data/ext/gobject-introspection/rb-gi-private-arg-info.h +24 -0
  16. data/ext/gobject-introspection/rb-gi-private-arguments-in.h +26 -0
  17. data/ext/gobject-introspection/rb-gi-private-arguments-out.h +28 -0
  18. data/ext/gobject-introspection/rb-gi-private-arguments.h +107 -0
  19. data/ext/gobject-introspection/rb-gi-private-array-type.h +26 -0
  20. data/ext/gobject-introspection/rb-gi-private-callback.h +41 -0
  21. data/ext/gobject-introspection/rb-gi-private-direction.h +24 -0
  22. data/ext/gobject-introspection/rb-gi-private-transfer.h +24 -0
  23. data/ext/gobject-introspection/rb-gi-private.h +11 -5
  24. data/ext/gobject-introspection/rb-gi-struct-info.c +2 -0
  25. data/ext/gobject-introspection/rb-gi-transfer.c +36 -0
  26. data/ext/gobject-introspection/rb-gi-type-info.c +1 -13
  27. data/ext/gobject-introspection/rb-gobject-introspection.c +4 -1
  28. data/ext/gobject-introspection/rb-gobject-introspection.h +5 -23
  29. data/lib/gobject-introspection/arg-info.rb +2 -0
  30. data/lib/gobject-introspection/callable-info.rb +1 -1
  31. data/lib/gobject-introspection/loader.rb +0 -39
  32. data/lib/gobject-introspection/type-tag.rb +39 -2
  33. metadata +21 -5
@@ -0,0 +1,850 @@
1
+ /* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * Copyright (C) 2012-2019 Ruby-GNOME Project Team
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18
+ * MA 02110-1301 USA
19
+ */
20
+
21
+ #include "rb-gi-private.h"
22
+
23
+ static gboolean
24
+ rb_gi_arg_info_may_be_null(GIArgInfo *arg_info)
25
+ {
26
+ #if GI_CHECK_VERSION(1, 42, 0)
27
+ return g_arg_info_may_be_null(arg_info);
28
+ #else
29
+ /*
30
+ GObject Introspection < 1.42 doesn't support "(nullable)" yet.
31
+ So, we assume that all argument may be NULL. It's danger but
32
+ convenient.
33
+ */
34
+ return TRUE;
35
+ #endif
36
+ }
37
+
38
+ static gboolean
39
+ rb_gi_is_registered_type(GIInfoType type)
40
+ {
41
+ switch (type) {
42
+ case GI_INFO_TYPE_STRUCT:
43
+ case GI_INFO_TYPE_BOXED:
44
+ case GI_INFO_TYPE_ENUM:
45
+ case GI_INFO_TYPE_FLAGS:
46
+ case GI_INFO_TYPE_OBJECT:
47
+ case GI_INFO_TYPE_INTERFACE:
48
+ case GI_INFO_TYPE_UNION:
49
+ return TRUE;
50
+ default:
51
+ return FALSE;
52
+ }
53
+ }
54
+
55
+ static void
56
+ rb_gi_arg_metadata_type_init(RBGIArgMetadataType *type,
57
+ GITypeInfo *type_info)
58
+ {
59
+ type->info = type_info;
60
+ type->tag = GI_TYPE_TAG_VOID;
61
+ type->interface_info = NULL;
62
+ type->interface_type = GI_INFO_TYPE_INVALID;
63
+ type->interface_gtype = G_TYPE_INVALID;
64
+
65
+ if (type->info) {
66
+ type->tag = g_type_info_get_tag(type->info);
67
+ }
68
+ if (type->tag == GI_TYPE_TAG_INTERFACE) {
69
+ type->interface_info = g_type_info_get_interface(type_info);
70
+ type->interface_type = g_base_info_get_type(type->interface_info);
71
+ if (rb_gi_is_registered_type(type->interface_type)) {
72
+ type->interface_gtype =
73
+ g_registered_type_info_get_g_type(type->interface_info);
74
+ }
75
+ }
76
+ }
77
+
78
+ static void
79
+ rb_gi_arg_metadata_type_clear(RBGIArgMetadataType *type)
80
+ {
81
+ if (type->interface_info) {
82
+ g_base_info_unref(type->interface_info);
83
+ }
84
+ if (type->info) {
85
+ g_base_info_unref(type->info);
86
+ }
87
+ }
88
+
89
+ static RBGIArgMetadata *
90
+ rb_gi_arg_metadata_new(GICallableInfo *callable_info, gint i)
91
+ {
92
+ RBGIArgMetadata *metadata;
93
+ GIArgInfo *arg_info;
94
+ GITypeInfo *type_info;
95
+
96
+ metadata = ALLOC(RBGIArgMetadata);
97
+ metadata->callable_info = callable_info;
98
+ arg_info = &(metadata->arg_info);
99
+ g_callable_info_load_arg(callable_info, i, arg_info);
100
+ metadata->name = g_base_info_get_name(arg_info);
101
+ type_info = g_arg_info_get_type(arg_info);
102
+ rb_gi_arg_metadata_type_init(&(metadata->type), type_info);
103
+ rb_gi_arg_metadata_type_init(&(metadata->element_type), NULL);
104
+ rb_gi_arg_metadata_type_init(&(metadata->key_type), NULL);
105
+ rb_gi_arg_metadata_type_init(&(metadata->value_type), NULL);
106
+ metadata->scope_type = g_arg_info_get_scope(arg_info);
107
+ metadata->direction = g_arg_info_get_direction(arg_info);
108
+ metadata->transfer = g_arg_info_get_ownership_transfer(arg_info);
109
+ metadata->array_type = GI_ARRAY_TYPE_C;
110
+ metadata->callback_p = (metadata->scope_type != GI_SCOPE_TYPE_INVALID);
111
+ metadata->closure_p = FALSE;
112
+ metadata->destroy_p = FALSE;
113
+ metadata->interface_p = (metadata->type.tag == GI_TYPE_TAG_INTERFACE);
114
+ metadata->array_p = (metadata->type.tag == GI_TYPE_TAG_ARRAY);
115
+ metadata->array_length_p = FALSE;
116
+ metadata->may_be_null_p = rb_gi_arg_info_may_be_null(arg_info);
117
+ metadata->pointer_p = g_type_info_is_pointer(type_info);
118
+ metadata->caller_allocates_p = g_arg_info_is_caller_allocates(arg_info);
119
+ metadata->zero_terminated_p = FALSE;
120
+ metadata->output_buffer_p = rb_gi_arg_info_is_output_buffer(arg_info);
121
+ metadata->index = i;
122
+ metadata->in_arg_index = -1;
123
+ metadata->closure_in_arg_index = -1;
124
+ metadata->destroy_in_arg_index = -1;
125
+ metadata->rb_arg_index = -1;
126
+ metadata->out_arg_index = -1;
127
+ metadata->in_arg = NULL;
128
+ metadata->out_arg = NULL;
129
+ metadata->rb_arg = Qnil;
130
+ metadata->array_metadata = NULL;
131
+ metadata->array_length_metadata = NULL;
132
+ metadata->array_length_arg = NULL;
133
+ metadata->free_func = NULL;
134
+ metadata->free_func_data = NULL;
135
+
136
+ switch (metadata->type.tag) {
137
+ case GI_TYPE_TAG_ARRAY:
138
+ metadata->zero_terminated_p =
139
+ g_type_info_is_zero_terminated(type_info);
140
+ metadata->array_type = g_type_info_get_array_type(type_info);
141
+ rb_gi_arg_metadata_type_init(&(metadata->element_type),
142
+ g_type_info_get_param_type(type_info, 0));
143
+ break;
144
+ case GI_TYPE_TAG_GLIST:
145
+ case GI_TYPE_TAG_GSLIST:
146
+ rb_gi_arg_metadata_type_init(&(metadata->element_type),
147
+ g_type_info_get_param_type(type_info, 0));
148
+ break;
149
+ case GI_TYPE_TAG_GHASH:
150
+ rb_gi_arg_metadata_type_init(&(metadata->key_type),
151
+ g_type_info_get_param_type(type_info, 0));
152
+ rb_gi_arg_metadata_type_init(&(metadata->value_type),
153
+ g_type_info_get_param_type(type_info, 1));
154
+ break;
155
+ default:
156
+ break;
157
+ }
158
+
159
+ return metadata;
160
+ }
161
+
162
+ static void
163
+ rb_gi_arg_metadata_free(RBGIArgMetadata *metadata)
164
+ {
165
+ rb_gi_arg_metadata_type_clear(&(metadata->value_type));
166
+ rb_gi_arg_metadata_type_clear(&(metadata->key_type));
167
+ rb_gi_arg_metadata_type_clear(&(metadata->element_type));
168
+ rb_gi_arg_metadata_type_clear(&(metadata->type));
169
+ xfree(metadata);
170
+ }
171
+
172
+ static void
173
+ rb_gi_arguments_allocate(RBGIArguments *args)
174
+ {
175
+ gint i, n_args;
176
+
177
+ n_args = g_callable_info_get_n_args(args->info);
178
+ for (i = 0; i < n_args; i++) {
179
+ GIArgument argument = {0};
180
+ RBGIArgMetadata *metadata;
181
+ GIDirection direction;
182
+
183
+ metadata = rb_gi_arg_metadata_new(args->info, i);
184
+
185
+ direction = metadata->direction;
186
+ if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) {
187
+ metadata->in_arg_index = args->in_args->len;
188
+ g_array_append_val(args->in_args, argument);
189
+ }
190
+ if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) {
191
+ metadata->out_arg_index = args->out_args->len;
192
+ g_array_append_val(args->out_args, argument);
193
+ }
194
+
195
+ g_ptr_array_add(args->metadata, metadata);
196
+ }
197
+
198
+ for (i = 0; i < n_args; i++) {
199
+ RBGIArgMetadata *metadata;
200
+ GIDirection direction;
201
+
202
+ metadata = g_ptr_array_index(args->metadata, i);
203
+ direction = metadata->direction;
204
+ if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) {
205
+ metadata->in_arg = &g_array_index(args->in_args,
206
+ GIArgument,
207
+ metadata->in_arg_index);
208
+ }
209
+ if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) {
210
+ metadata->out_arg = &g_array_index(args->out_args,
211
+ GIArgument,
212
+ metadata->out_arg_index);
213
+ }
214
+ }
215
+ }
216
+
217
+ static void
218
+ rb_gi_arguments_fill_metadata_callback(RBGIArguments *args)
219
+ {
220
+ GPtrArray *metadata = args->metadata;
221
+ guint i;
222
+
223
+ for (i = 0; i < metadata->len; i++) {
224
+ RBGIArgMetadata *callback_metadata;
225
+ GIArgInfo *arg_info;
226
+ gint closure_index;
227
+ gint destroy_index;
228
+
229
+ callback_metadata = g_ptr_array_index(metadata, i);
230
+
231
+ arg_info = &(callback_metadata->arg_info);
232
+ closure_index = g_arg_info_get_closure(arg_info);
233
+ if (closure_index != -1) {
234
+ RBGIArgMetadata *closure_metadata;
235
+ closure_metadata = g_ptr_array_index(metadata, closure_index);
236
+ closure_metadata->closure_p = TRUE;
237
+ callback_metadata->closure_in_arg_index =
238
+ closure_metadata->in_arg_index;
239
+ }
240
+
241
+ destroy_index = g_arg_info_get_destroy(arg_info);
242
+ if (destroy_index != -1) {
243
+ RBGIArgMetadata *destroy_metadata;
244
+ destroy_metadata = g_ptr_array_index(args->metadata, destroy_index);
245
+ destroy_metadata->destroy_p = TRUE;
246
+ callback_metadata->destroy_in_arg_index =
247
+ destroy_metadata->in_arg_index;
248
+ }
249
+ }
250
+ }
251
+
252
+ static void
253
+ rb_gi_arguments_fill_metadata_array(RBGIArguments *args)
254
+ {
255
+ GPtrArray *metadata = args->metadata;
256
+ guint i;
257
+
258
+ for (i = 0; i < metadata->len; i++) {
259
+ RBGIArgMetadata *array_metadata;
260
+ RBGIArgMetadata *array_length_metadata;
261
+ GITypeInfo *type_info;
262
+ gint array_length_index = -1;
263
+
264
+ array_metadata = g_ptr_array_index(metadata, i);
265
+ type_info = array_metadata->type.info;
266
+ if (!array_metadata->array_p) {
267
+ continue;
268
+ }
269
+
270
+ array_length_index = g_type_info_get_array_length(type_info);
271
+ if (array_length_index == -1) {
272
+ continue;
273
+ }
274
+
275
+ array_length_metadata = g_ptr_array_index(metadata, array_length_index);
276
+ array_length_metadata->array_length_p = TRUE;
277
+ array_length_metadata->rb_arg_index = -1;
278
+ array_length_metadata->array_metadata = array_metadata;
279
+ array_metadata->array_length_metadata = array_length_metadata;
280
+ if (array_length_metadata->in_arg) {
281
+ array_metadata->array_length_arg = array_length_metadata->in_arg;
282
+ } else {
283
+ array_metadata->array_length_arg = array_length_metadata->out_arg;
284
+ }
285
+ }
286
+ }
287
+
288
+ static void
289
+ rb_gi_arguments_fill_metadata_array_from_callable_info(RBGIArguments *args)
290
+ {
291
+ GICallbackInfo *info = args->info;
292
+ GPtrArray *metadata = args->metadata;
293
+ GITypeInfo return_type_info;
294
+ RBGIArgMetadata *array_length_metadata;
295
+ gint array_length_index = -1;
296
+
297
+ g_callable_info_load_return_type(info, &return_type_info);
298
+ if (g_type_info_get_tag(&return_type_info) != GI_TYPE_TAG_ARRAY) {
299
+ return;
300
+ }
301
+
302
+ array_length_index = g_type_info_get_array_length(&return_type_info);
303
+ if (array_length_index == -1) {
304
+ return;
305
+ }
306
+
307
+ array_length_metadata = g_ptr_array_index(metadata, array_length_index);
308
+ array_length_metadata->array_length_p = TRUE;
309
+ array_length_metadata->rb_arg_index = -1;
310
+ }
311
+
312
+ static void
313
+ rb_gi_arguments_fill_metadata_rb_arg_index(RBGIArguments *args)
314
+ {
315
+ guint i;
316
+ gint rb_arg_index = 0;
317
+
318
+ for (i = 0; i < args->metadata->len; i++) {
319
+ RBGIArgMetadata *metadata;
320
+
321
+ metadata = g_ptr_array_index(args->metadata, i);
322
+
323
+ if (metadata->callback_p) {
324
+ continue;
325
+ }
326
+
327
+ if (metadata->closure_p) {
328
+ continue;
329
+ }
330
+
331
+ if (metadata->destroy_p) {
332
+ continue;
333
+ }
334
+
335
+ if (metadata->array_length_p) {
336
+ continue;
337
+ }
338
+
339
+ if (metadata->in_arg_index == -1 &&
340
+ !metadata->output_buffer_p) {
341
+ continue;
342
+ }
343
+
344
+ metadata->rb_arg_index = rb_arg_index;
345
+ if (RARRAY_LEN(args->rb_args) > metadata->rb_arg_index) {
346
+ metadata->rb_arg =
347
+ RARRAY_AREF(args->rb_args, metadata->rb_arg_index);
348
+ }
349
+ rb_arg_index++;
350
+ }
351
+ }
352
+
353
+ static void
354
+ rb_gi_arguments_fill_metadata(RBGIArguments *args)
355
+ {
356
+ rb_gi_arguments_fill_metadata_callback(args);
357
+ rb_gi_arguments_fill_metadata_array(args);
358
+ rb_gi_arguments_fill_metadata_array_from_callable_info(args);
359
+ if (args->rb_mode_p) {
360
+ rb_gi_arguments_fill_metadata_rb_arg_index(args);
361
+ }
362
+ }
363
+
364
+ static void
365
+ rb_gi_arguments_fill_rb_args(RBGIArguments *args)
366
+ {
367
+ rb_gi_arguments_in_init(args);
368
+ rb_gi_arguments_out_init(args);
369
+ }
370
+
371
+ static void
372
+ rb_gi_arguments_fill_raw_args(RBGIArguments *args)
373
+ {
374
+ guint i;
375
+
376
+ for (i = 0; i < args->metadata->len; i++) {
377
+ RBGIArgMetadata *metadata;
378
+
379
+ metadata = g_ptr_array_index(args->metadata, i);
380
+ if (metadata->direction == GI_DIRECTION_INOUT) {
381
+ GIArgument *argument = &g_array_index(args->in_args,
382
+ GIArgument,
383
+ metadata->in_arg_index);
384
+ argument->v_pointer = *((gpointer *)(args->raw_args[i]));
385
+ }
386
+ }
387
+
388
+ rb_gi_arguments_in_init(args);
389
+ rb_gi_arguments_out_init(args);
390
+ }
391
+
392
+ static void
393
+ rb_gi_arguments_metadata_free(gpointer data)
394
+ {
395
+ RBGIArgMetadata *metadata = data;
396
+ if (metadata->scope_type == GI_SCOPE_TYPE_ASYNC ||
397
+ metadata->scope_type == GI_SCOPE_TYPE_NOTIFIED) {
398
+ return;
399
+ }
400
+ rb_gi_arg_metadata_free(metadata);
401
+ }
402
+
403
+ static gboolean
404
+ rb_gi_arguments_gobject_based_p(RBGIArguments *args)
405
+ {
406
+ GIBaseInfo *container_info;
407
+ GIRegisteredTypeInfo *registered_type_info;
408
+
409
+ container_info = g_base_info_get_container(args->info);
410
+ if (g_base_info_get_type(container_info) != GI_INFO_TYPE_STRUCT) {
411
+ return TRUE;
412
+ }
413
+
414
+ registered_type_info = (GIRegisteredTypeInfo *)container_info;
415
+ if (g_registered_type_info_get_type_init(registered_type_info)) {
416
+ return TRUE;
417
+ }
418
+
419
+ return FALSE;
420
+ }
421
+
422
+ void
423
+ rb_gi_arguments_init(RBGIArguments *args,
424
+ GICallableInfo *info,
425
+ VALUE rb_receiver,
426
+ VALUE rb_args,
427
+ void **raw_args)
428
+ {
429
+ args->info = info;
430
+ args->namespace = g_base_info_get_namespace(info);
431
+ if (GI_IS_FUNCTION_INFO(info)) {
432
+ args->name = g_function_info_get_symbol((GIFunctionInfo *)info);
433
+ } else {
434
+ args->name = g_base_info_get_name(info);
435
+ }
436
+ args->rb_receiver = rb_receiver;
437
+ args->receiver_type_class = NULL;
438
+ args->rb_args = rb_args;
439
+ args->raw_args = raw_args;
440
+ args->in_args = g_array_new(FALSE, FALSE, sizeof(GIArgument));
441
+ args->out_args = g_array_new(FALSE, FALSE, sizeof(GIArgument));
442
+ args->metadata =
443
+ g_ptr_array_new_with_free_func(rb_gi_arguments_metadata_free);
444
+ args->rb_mode_p = !(NIL_P(rb_args));
445
+
446
+ if (!NIL_P(rb_receiver)) {
447
+ GIArgument receiver;
448
+ VALUE rb_receiver_class;
449
+ rb_receiver_class = rb_class_of(rb_receiver);
450
+ if (rb_gi_arguments_gobject_based_p(args) ||
451
+ rb_respond_to(rb_receiver_class, rb_intern("gtype"))) {
452
+ receiver.v_pointer = RVAL2GOBJ(rb_receiver);
453
+ } else if (RVAL2CBOOL(rb_obj_is_kind_of(rb_receiver, rb_cClass)) &&
454
+ rb_respond_to(rb_receiver, rb_intern("gtype"))) {
455
+ args->receiver_type_class =
456
+ g_type_class_ref(CLASS2GTYPE(rb_receiver));
457
+ receiver.v_pointer = args->receiver_type_class;
458
+ } else {
459
+ receiver.v_pointer = rb_gi_struct_get_raw(rb_receiver, G_TYPE_NONE);
460
+ }
461
+ if (receiver.v_pointer) {
462
+ g_array_append_val(args->in_args, receiver);
463
+ }
464
+ }
465
+
466
+ rb_gi_arguments_allocate(args);
467
+ rb_gi_arguments_fill_metadata(args);
468
+ if (args->rb_mode_p) {
469
+ rb_gi_arguments_fill_rb_args(args);
470
+ } else {
471
+ rb_gi_arguments_fill_raw_args(args);
472
+ }
473
+ }
474
+
475
+ void
476
+ rb_gi_arguments_clear(RBGIArguments *args)
477
+ {
478
+ rb_gi_arguments_in_clear(args);
479
+ rb_gi_arguments_out_clear(args);
480
+
481
+ if (args->receiver_type_class) {
482
+ g_type_class_unref(args->receiver_type_class);
483
+ }
484
+ g_array_unref(args->in_args);
485
+ g_array_unref(args->out_args);
486
+ g_ptr_array_unref(args->metadata);
487
+ }
488
+
489
+ VALUE
490
+ rb_gi_arguments_get_rb_return_value(RBGIArguments *args,
491
+ GIArgument *return_value)
492
+ {
493
+ /* TODO */
494
+ VALUE rb_return_value = GI_RETURN_ARGUMENT2RVAL(args->info,
495
+ return_value,
496
+ args->in_args,
497
+ args->out_args,
498
+ args->metadata);
499
+ return rb_return_value;
500
+ }
501
+
502
+ VALUE
503
+ rb_gi_arguments_get_rb_out_args(RBGIArguments *args)
504
+ {
505
+ return rb_gi_arguments_out_to_ruby(args);
506
+ }
507
+
508
+ static void
509
+ rb_gi_arguments_fill_raw_result_interface(RBGIArguments *args,
510
+ VALUE rb_result,
511
+ gpointer raw_result,
512
+ GITypeInfo *type_info,
513
+ G_GNUC_UNUSED GITransfer transfer /* TODO */,
514
+ gboolean is_return_value)
515
+ {
516
+ GIBaseInfo *interface_info;
517
+ GIInfoType interface_type;
518
+ GIFFIReturnValue *ffi_return_value = raw_result;
519
+
520
+ interface_info = g_type_info_get_interface(type_info);
521
+ interface_type = g_base_info_get_type(interface_info);
522
+
523
+ switch (interface_type) {
524
+ case GI_INFO_TYPE_INVALID:
525
+ case GI_INFO_TYPE_FUNCTION:
526
+ case GI_INFO_TYPE_CALLBACK:
527
+ case GI_INFO_TYPE_STRUCT:
528
+ case GI_INFO_TYPE_BOXED:
529
+ rb_raise(rb_eNotImpError,
530
+ "TODO: %s::%s: out raw result(interface)[%s]: <%s>",
531
+ args->namespace,
532
+ args->name,
533
+ g_info_type_to_string(interface_type),
534
+ g_base_info_get_name(interface_info));
535
+ break;
536
+ case GI_INFO_TYPE_ENUM:
537
+ {
538
+ gint32 value;
539
+ GType gtype = g_registered_type_info_get_g_type(interface_info);
540
+ if (gtype == G_TYPE_NONE) {
541
+ value = NUM2INT(rb_result);
542
+ } else {
543
+ value = RVAL2GENUM(rb_result, gtype);
544
+ }
545
+ if (is_return_value) {
546
+ ffi_return_value->v_ulong = value;
547
+ } else {
548
+ *((gint *)raw_result) = value;
549
+ }
550
+ }
551
+ break;
552
+ case GI_INFO_TYPE_FLAGS:
553
+ case GI_INFO_TYPE_OBJECT:
554
+ case GI_INFO_TYPE_INTERFACE:
555
+ case GI_INFO_TYPE_CONSTANT:
556
+ rb_raise(rb_eNotImpError,
557
+ "TODO: %s::%s: out raw result(interface)[%s]: <%s>",
558
+ g_base_info_get_namespace(args->info),
559
+ g_base_info_get_name(args->info),
560
+ g_info_type_to_string(interface_type),
561
+ g_base_info_get_name(interface_info));
562
+ break;
563
+ case GI_INFO_TYPE_INVALID_0:
564
+ g_assert_not_reached();
565
+ break;
566
+ case GI_INFO_TYPE_UNION:
567
+ case GI_INFO_TYPE_VALUE:
568
+ case GI_INFO_TYPE_SIGNAL:
569
+ case GI_INFO_TYPE_VFUNC:
570
+ case GI_INFO_TYPE_PROPERTY:
571
+ case GI_INFO_TYPE_FIELD:
572
+ case GI_INFO_TYPE_ARG:
573
+ case GI_INFO_TYPE_TYPE:
574
+ case GI_INFO_TYPE_UNRESOLVED:
575
+ default:
576
+ rb_raise(rb_eNotImpError,
577
+ "TODO: %s::%s: out raw result(interface)[%s]: <%s>",
578
+ g_base_info_get_namespace(args->info),
579
+ g_base_info_get_name(args->info),
580
+ g_info_type_to_string(interface_type),
581
+ g_base_info_get_name(interface_info));
582
+ break;
583
+ }
584
+
585
+ g_base_info_unref(interface_info);
586
+ }
587
+
588
+ /*
589
+ We need to cast from different type for return value. (We don't
590
+ need it for out arguments.) Because of libffi specification:
591
+
592
+ https://github.com/libffi/libffi/blob/master/doc/libffi.texi#L190
593
+
594
+ @var{rvalue} is a pointer to a chunk of memory that will hold the
595
+ result of the function call. This must be large enough to hold the
596
+ result, no smaller than the system register size (generally 32 or 64
597
+ bits), and must be suitably aligned; it is the caller's responsibility
598
+ to ensure this. If @var{cif} declares that the function returns
599
+ @code{void} (using @code{ffi_type_void}), then @var{rvalue} is
600
+ ignored.
601
+
602
+ https://github.com/libffi/libffi/blob/master/doc/libffi.texi#L198
603
+
604
+ In most situations, @samp{libffi} will handle promotion according to
605
+ the ABI. However, for historical reasons, there is a special case
606
+ with return values that must be handled by your code. In particular,
607
+ for integral (not @code{struct}) types that are narrower than the
608
+ system register size, the return value will be widened by
609
+ @samp{libffi}. @samp{libffi} provides a type, @code{ffi_arg}, that
610
+ can be used as the return type. For example, if the CIF was defined
611
+ with a return type of @code{char}, @samp{libffi} will try to store a
612
+ full @code{ffi_arg} into the return value.
613
+
614
+ See also:
615
+ * https://github.com/ruby-gnome/ruby-gnome/issues/758#issuecomment-243149237
616
+ * https://github.com/libffi/libffi/pull/216
617
+
618
+ This ffi_return_value case implementation is based on
619
+ gi_type_info_extract_ffi_return_value().
620
+ */
621
+ static void
622
+ rb_gi_arguments_fill_raw_result(RBGIArguments *args,
623
+ VALUE rb_result,
624
+ gpointer raw_result,
625
+ GITypeInfo *type_info,
626
+ GITransfer transfer,
627
+ gboolean is_return_value)
628
+ {
629
+ GIFFIReturnValue *ffi_return_value = raw_result;
630
+ GITypeTag type_tag;
631
+
632
+ type_tag = g_type_info_get_tag(type_info);
633
+ switch (type_tag) {
634
+ case GI_TYPE_TAG_VOID:
635
+ g_assert_not_reached();
636
+ break;
637
+ case GI_TYPE_TAG_BOOLEAN:
638
+ if (is_return_value) {
639
+ ffi_return_value->v_ulong = RVAL2CBOOL(rb_result);
640
+ } else {
641
+ *((gboolean *)raw_result) = RVAL2CBOOL(rb_result);
642
+ }
643
+ break;
644
+ case GI_TYPE_TAG_INT8:
645
+ if (is_return_value) {
646
+ ffi_return_value->v_long = NUM2CHR(rb_result);
647
+ } else {
648
+ *((gint8 *)raw_result) = NUM2CHR(rb_result);
649
+ }
650
+ break;
651
+ case GI_TYPE_TAG_UINT8:
652
+ if (is_return_value) {
653
+ ffi_return_value->v_ulong = (guint8)NUM2CHR(rb_result);
654
+ } else {
655
+ *((guint8 *)raw_result) = (guint8)NUM2CHR(rb_result);
656
+ }
657
+ break;
658
+ case GI_TYPE_TAG_INT16:
659
+ if (is_return_value) {
660
+ ffi_return_value->v_long = NUM2SHORT(rb_result);
661
+ } else {
662
+ *((gint16 *)raw_result) = NUM2SHORT(rb_result);
663
+ }
664
+ break;
665
+ case GI_TYPE_TAG_UINT16:
666
+ if (is_return_value) {
667
+ ffi_return_value->v_ulong = NUM2USHORT(rb_result);
668
+ } else {
669
+ *((guint16 *)raw_result) = NUM2USHORT(rb_result);
670
+ }
671
+ break;
672
+ case GI_TYPE_TAG_INT32:
673
+ if (is_return_value) {
674
+ ffi_return_value->v_long = NUM2INT(rb_result);
675
+ } else {
676
+ *((gint32 *)raw_result) = NUM2INT(rb_result);
677
+ }
678
+ break;
679
+ case GI_TYPE_TAG_UINT32:
680
+ if (is_return_value) {
681
+ ffi_return_value->v_ulong = NUM2UINT(rb_result);
682
+ } else {
683
+ *((guint32 *)raw_result) = NUM2UINT(rb_result);
684
+ }
685
+ break;
686
+ case GI_TYPE_TAG_INT64:
687
+ *((gint64 *)raw_result) = NUM2LL(rb_result);
688
+ break;
689
+ case GI_TYPE_TAG_UINT64:
690
+ *((guint64 *)raw_result) = NUM2ULL(rb_result);
691
+ break;
692
+ case GI_TYPE_TAG_FLOAT:
693
+ *((gfloat *)raw_result) = NUM2DBL(rb_result);
694
+ break;
695
+ case GI_TYPE_TAG_DOUBLE:
696
+ *((gdouble *)raw_result) = NUM2DBL(rb_result);
697
+ break;
698
+ case GI_TYPE_TAG_GTYPE:
699
+ if (is_return_value) {
700
+ ffi_return_value->v_ulong = rbgobj_gtype_from_ruby(rb_result);
701
+ } else {
702
+ *((gsize *)raw_result) = rbgobj_gtype_from_ruby(rb_result);
703
+ }
704
+ break;
705
+ case GI_TYPE_TAG_UTF8:
706
+ if (is_return_value) {
707
+ ffi_return_value->v_ulong =
708
+ (gulong)RVAL2CSTR_ACCEPT_SYMBOL(rb_result);
709
+ } else {
710
+ *((gchar **)raw_result) =
711
+ (gchar *)RVAL2CSTR_ACCEPT_SYMBOL(rb_result);
712
+ }
713
+ break;
714
+ case GI_TYPE_TAG_FILENAME:
715
+ rb_raise(rb_eNotImpError,
716
+ "TODO: %s::%s: out raw result(%s)",
717
+ args->namespace,
718
+ args->name,
719
+ g_type_tag_to_string(type_tag));
720
+ /* if (is_return_value) { */
721
+ /* ffi_return_value->v_ulong = */
722
+ /* (gulong)rbg_filename_from_ruby(rb_result); */
723
+ /* } else { */
724
+ /* *((gchar **)raw_result) = */
725
+ /* (gchar *)rbg_filename_from_ruby(rb_result); */
726
+ /* } */
727
+ /* free */
728
+ break;
729
+ case GI_TYPE_TAG_ARRAY:
730
+ rb_raise(rb_eNotImpError,
731
+ "TODO: %s::%s: out raw result(%s)",
732
+ args->namespace,
733
+ args->name,
734
+ g_type_tag_to_string(type_tag));
735
+ /* if (is_return_value) { */
736
+ /* ffi_return_value->v_ulong = (gulong)(argument.v_pointer); */
737
+ /* } else { */
738
+ /* *((gpointer *)raw_result) = argument.v_pointer; */
739
+ /* } */
740
+ break;
741
+ case GI_TYPE_TAG_INTERFACE:
742
+ rb_gi_arguments_fill_raw_result_interface(args,
743
+ rb_result,
744
+ raw_result,
745
+ type_info,
746
+ transfer,
747
+ is_return_value);
748
+ break;
749
+ case GI_TYPE_TAG_GLIST:
750
+ case GI_TYPE_TAG_GSLIST:
751
+ case GI_TYPE_TAG_GHASH:
752
+ rb_raise(rb_eNotImpError,
753
+ "TODO: %s::%s: out raw result(%s)",
754
+ args->namespace,
755
+ args->name,
756
+ g_type_tag_to_string(type_tag));
757
+ /* if (is_return_value) { */
758
+ /* ffi_return_value->v_ulong = (gulong)(argument.v_pointer); */
759
+ /* } else { */
760
+ /* *((gpointer *)raw_result) = argument.v_pointer; */
761
+ /* } */
762
+ break;
763
+ case GI_TYPE_TAG_ERROR:
764
+ rb_raise(rb_eNotImpError,
765
+ "TODO: %s::%s: out raw result(%s)",
766
+ args->namespace,
767
+ args->name,
768
+ g_type_tag_to_string(type_tag));
769
+ /* if (is_return_value) { */
770
+ /* ffi_return_value->v_ulong = (gulong)(argument.v_pointer); */
771
+ /* } else { */
772
+ /* *((GError **)raw_result) = argument.v_pointer; */
773
+ /* } */
774
+ break;
775
+ case GI_TYPE_TAG_UNICHAR:
776
+ if (is_return_value) {
777
+ ffi_return_value->v_ulong = NUM2UINT(rb_result);
778
+ } else {
779
+ *((gunichar *)raw_result) = NUM2UINT(rb_result);
780
+ }
781
+ break;
782
+ default:
783
+ g_assert_not_reached();
784
+ break;
785
+ }
786
+ }
787
+
788
+ void
789
+ rb_gi_arguments_fill_raw_results(RBGIArguments *args,
790
+ VALUE rb_results,
791
+ gpointer raw_return_value)
792
+ {
793
+ int i_rb_result = 0;
794
+ guint i;
795
+ GITypeInfo *return_type_info;
796
+ GITypeTag return_type_tag;
797
+
798
+ return_type_info = g_callable_info_get_return_type(args->info);
799
+ return_type_tag = g_type_info_get_tag(return_type_info);
800
+ if (return_type_tag != GI_TYPE_TAG_VOID) {
801
+ GITransfer transfer;
802
+ transfer = g_callable_info_get_caller_owns(args->info);
803
+ if (args->out_args->len == 0) {
804
+ VALUE rb_return_value = rb_results;
805
+ rb_gi_arguments_fill_raw_result(args,
806
+ rb_return_value,
807
+ raw_return_value,
808
+ return_type_info,
809
+ transfer,
810
+ TRUE);
811
+ } else {
812
+ rb_gi_arguments_fill_raw_result(args,
813
+ RARRAY_AREF(rb_results, i_rb_result),
814
+ raw_return_value,
815
+ return_type_info,
816
+ transfer,
817
+ TRUE);
818
+ i_rb_result++;
819
+ }
820
+ }
821
+ g_base_info_unref(return_type_info);
822
+
823
+ for (i = 0; i < args->metadata->len; i++) {
824
+ RBGIArgMetadata *metadata;
825
+ GIArgument *argument;
826
+ GITypeInfo *type_info;
827
+ GITransfer transfer;
828
+
829
+ metadata = g_ptr_array_index(args->metadata, i);
830
+
831
+ /* TODO: support GI_DIRECTION_INOUT */
832
+ if (metadata->direction != GI_DIRECTION_OUT) {
833
+ continue;
834
+ }
835
+
836
+ argument = &g_array_index(args->out_args,
837
+ GIArgument,
838
+ metadata->out_arg_index);
839
+ type_info = g_arg_info_get_type(&(metadata->arg_info));
840
+ transfer = g_arg_info_get_ownership_transfer(&(metadata->arg_info));
841
+ rb_gi_arguments_fill_raw_result(args,
842
+ RARRAY_AREF(rb_results, i_rb_result),
843
+ argument->v_pointer,
844
+ return_type_info,
845
+ transfer,
846
+ FALSE);
847
+ i_rb_result++;
848
+ g_base_info_unref(type_info);
849
+ }
850
+ }