gobject-introspection 3.3.8 → 3.3.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
@@ -1,6 +1,6 @@
1
1
  /* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
2
2
  /*
3
- * Copyright (C) 2012-2019 Ruby-GNOME2 Project Team
3
+ * Copyright (C) 2012-2019 Ruby-GNOME Project Team
4
4
  *
5
5
  * This library is free software; you can redistribute it and/or
6
6
  * modify it under the terms of the GNU Lesser General Public
@@ -34,26 +34,7 @@
34
34
  #define RG_TARGET_NAMESPACE rb_cGIFunctionInfo
35
35
  #define SELF(self) RVAL2GI_FUNCTION_INFO(self)
36
36
 
37
- typedef struct _RBGICallback {
38
- GIArgInfo *arg_info;
39
- GITypeInfo *type_info;
40
- GICallbackInfo *callback_info;
41
- ffi_cif cif;
42
- ffi_closure *closure;
43
- } RBGICallback;
44
-
45
- struct RBGICallbackData_ {
46
- RBGICallback *callback;
47
- RBGIArgMetadata *metadata;
48
- VALUE rb_callback;
49
- GObject *owner;
50
- VALUE rb_owner;
51
- };
52
-
53
37
  static VALUE RG_TARGET_NAMESPACE;
54
- static VALUE rb_cGLibError;
55
- static const char *callbacks_key = "gi_callbacks";
56
- static GPtrArray *callback_finders;
57
38
 
58
39
  GType
59
40
  gi_function_info_get_type(void)
@@ -118,1320 +99,6 @@ rg_vfunc(VALUE self)
118
99
  return GI_BASE_INFO2RVAL(g_function_info_get_vfunc(info));
119
100
  }
120
101
 
121
- static void
122
- allocate_arguments(GICallableInfo *info,
123
- GArray *in_args, GArray *out_args,
124
- GPtrArray *args_metadata)
125
- {
126
- gint i, n_args;
127
-
128
- n_args = g_callable_info_get_n_args(info);
129
- for (i = 0; i < n_args; i++) {
130
- GIArgument argument;
131
- RBGIArgMetadata *metadata;
132
- GIArgInfo *arg_info;
133
- GIDirection direction;
134
-
135
- memset(&argument, 0, sizeof(GIArgument));
136
-
137
- metadata = ALLOC(RBGIArgMetadata);
138
- metadata->callable_info = info;
139
- arg_info = &(metadata->arg_info);
140
- g_callable_info_load_arg(info, i, arg_info);
141
- metadata->scope_type = g_arg_info_get_scope(arg_info);
142
- metadata->direction = g_arg_info_get_direction(arg_info);
143
- metadata->callback_p = (metadata->scope_type != GI_SCOPE_TYPE_INVALID);
144
- metadata->closure_p = FALSE;
145
- metadata->destroy_p = FALSE;
146
- metadata->array_p = FALSE;
147
- metadata->array_length_p = FALSE;
148
- metadata->in_arg_index = -1;
149
- metadata->closure_in_arg_index = -1;
150
- metadata->destroy_in_arg_index = -1;
151
- metadata->array_in_arg_index = -1;
152
- metadata->array_length_in_arg_index = -1;
153
- metadata->array_length_arg_index = -1;
154
- metadata->rb_arg_index = -1;
155
- metadata->out_arg_index = -1;
156
-
157
- direction = metadata->direction;
158
- if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) {
159
- metadata->in_arg_index = in_args->len;
160
- g_array_append_val(in_args, argument);
161
- }
162
- if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) {
163
- metadata->out_arg_index = out_args->len;
164
- g_array_append_val(out_args, argument);
165
- }
166
-
167
- g_ptr_array_add(args_metadata, metadata);
168
- }
169
- }
170
-
171
- static void
172
- fill_metadata_callback(GPtrArray *args_metadata)
173
- {
174
- guint i;
175
-
176
- for (i = 0; i < args_metadata->len; i++) {
177
- RBGIArgMetadata *metadata;
178
- GIArgInfo *arg_info;
179
- gint closure_index;
180
- gint destroy_index;
181
-
182
- metadata = g_ptr_array_index(args_metadata, i);
183
-
184
- arg_info = &(metadata->arg_info);
185
- closure_index = g_arg_info_get_closure(arg_info);
186
- if (closure_index != -1) {
187
- RBGIArgMetadata *closure_metadata;
188
- closure_metadata = g_ptr_array_index(args_metadata, closure_index);
189
- closure_metadata->closure_p = TRUE;
190
- metadata->closure_in_arg_index = closure_metadata->in_arg_index;
191
- }
192
-
193
- destroy_index = g_arg_info_get_destroy(arg_info);
194
- if (destroy_index != -1) {
195
- RBGIArgMetadata *destroy_metadata;
196
- destroy_metadata = g_ptr_array_index(args_metadata, destroy_index);
197
- destroy_metadata->destroy_p = TRUE;
198
- metadata->destroy_in_arg_index = destroy_metadata->in_arg_index;
199
- }
200
- }
201
- }
202
-
203
- static void
204
- fill_metadata_array(GPtrArray *args_metadata)
205
- {
206
- guint i;
207
-
208
- for (i = 0; i < args_metadata->len; i++) {
209
- RBGIArgMetadata *metadata;
210
- RBGIArgMetadata *array_length_metadata;
211
- GIArgInfo *arg_info;
212
- GITypeInfo type_info;
213
- gint array_length_index = -1;
214
-
215
- metadata = g_ptr_array_index(args_metadata, i);
216
- arg_info = &(metadata->arg_info);
217
-
218
- g_arg_info_load_type(arg_info, &type_info);
219
- if (g_type_info_get_tag(&type_info) != GI_TYPE_TAG_ARRAY) {
220
- continue;
221
- }
222
- metadata->array_p = TRUE;
223
-
224
- array_length_index = g_type_info_get_array_length(&type_info);
225
- if (array_length_index == -1) {
226
- continue;
227
- }
228
-
229
- array_length_metadata = g_ptr_array_index(args_metadata,
230
- array_length_index);
231
- array_length_metadata->array_length_p = TRUE;
232
- array_length_metadata->rb_arg_index = -1;
233
- array_length_metadata->array_in_arg_index =
234
- metadata->in_arg_index;
235
- metadata->array_length_in_arg_index =
236
- array_length_metadata->in_arg_index;
237
- metadata->array_length_arg_index = array_length_index;
238
- }
239
- }
240
-
241
- static void
242
- fill_metadata_array_from_callable_info(GPtrArray *args_metadata,
243
- GICallableInfo *info)
244
- {
245
- GITypeInfo return_type_info;
246
- RBGIArgMetadata *array_length_metadata;
247
- gint array_length_index = -1;
248
-
249
- g_callable_info_load_return_type(info, &return_type_info);
250
- if (g_type_info_get_tag(&return_type_info) != GI_TYPE_TAG_ARRAY) {
251
- return;
252
- }
253
-
254
- array_length_index = g_type_info_get_array_length(&return_type_info);
255
- if (array_length_index == -1) {
256
- return;
257
- }
258
-
259
- array_length_metadata = g_ptr_array_index(args_metadata, array_length_index);
260
- array_length_metadata->array_length_p = TRUE;
261
- array_length_metadata->rb_arg_index = -1;
262
- }
263
-
264
- static void
265
- fill_metadata_rb_arg_index(GPtrArray *args_metadata)
266
- {
267
- guint i;
268
- gint rb_arg_index = 0;
269
-
270
- for (i = 0; i < args_metadata->len; i++) {
271
- RBGIArgMetadata *metadata;
272
-
273
- metadata = g_ptr_array_index(args_metadata, i);
274
-
275
- if (metadata->callback_p) {
276
- continue;
277
- }
278
-
279
- if (metadata->closure_p) {
280
- continue;
281
- }
282
-
283
- if (metadata->destroy_p) {
284
- continue;
285
- }
286
-
287
- if (metadata->array_length_p) {
288
- continue;
289
- }
290
-
291
- if (metadata->in_arg_index == -1) {
292
- continue;
293
- }
294
-
295
- metadata->rb_arg_index = rb_arg_index;
296
- rb_arg_index++;
297
- }
298
- }
299
-
300
- static void
301
- fill_metadata(GPtrArray *args_metadata, GICallableInfo *info)
302
- {
303
- fill_metadata_callback(args_metadata);
304
- fill_metadata_array(args_metadata);
305
- fill_metadata_array_from_callable_info(args_metadata, info);
306
- fill_metadata_rb_arg_index(args_metadata);
307
- }
308
-
309
- static void
310
- rb_gi_callback_free(RBGICallback *callback)
311
- {
312
- g_callable_info_free_closure(callback->callback_info,
313
- callback->closure);
314
- g_base_info_unref(callback->callback_info);
315
- g_base_info_unref(callback->type_info);
316
- xfree(callback);
317
- }
318
-
319
- static void
320
- rb_gi_callback_data_weak_notify(gpointer data,
321
- G_GNUC_UNUSED GObject *where_the_object_was)
322
- {
323
- RBGICallbackData *callback_data = data;
324
- callback_data->owner = NULL;
325
- }
326
-
327
- void
328
- rb_gi_callback_data_free(RBGICallbackData *callback_data)
329
- {
330
- if (callback_data->callback) {
331
- rb_gi_callback_free(callback_data->callback);
332
- }
333
- if (callback_data->owner) {
334
- VALUE rb_owner;
335
- g_object_weak_unref(callback_data->owner,
336
- rb_gi_callback_data_weak_notify,
337
- callback_data);
338
- rb_owner = rbgobj_ruby_object_from_instance2(callback_data->owner,
339
- FALSE);
340
- if (!NIL_P(rb_owner)) {
341
- rbgobj_object_remove_relative(rb_owner, callback_data->rb_callback);
342
- }
343
- }
344
- if (!NIL_P(callback_data->rb_owner)) {
345
- rbgobj_remove_relative(callback_data->rb_owner,
346
- (ID)0,
347
- callback_data->rb_callback);
348
- }
349
- xfree(callback_data->metadata);
350
- xfree(callback_data);
351
- }
352
-
353
- RBGIArgMetadata *
354
- rb_gi_callback_data_get_metadata(RBGICallbackData *callback_data)
355
- {
356
- return callback_data->metadata;
357
- }
358
-
359
- VALUE
360
- rb_gi_callback_data_get_rb_callback(RBGICallbackData *callback_data)
361
- {
362
- return callback_data->rb_callback;
363
- }
364
-
365
- static void
366
- rb_gi_callback_data_destroy_notify(gpointer data)
367
- {
368
- RBGICallbackData *callback_data = data;
369
- rb_gi_callback_data_free(callback_data);
370
- }
371
-
372
- static gpointer
373
- find_callback_function(GIArgInfo *info)
374
- {
375
- guint i;
376
- gpointer callback = NULL;
377
-
378
- for (i = 0; i < callback_finders->len; i++) {
379
- RBGICallbackFinderFunc finder = g_ptr_array_index(callback_finders, i);
380
- callback = finder(info);
381
- if (callback) {
382
- break;
383
- }
384
- }
385
-
386
- return callback;
387
- }
388
-
389
- void
390
- rb_gi_callback_register_finder(RBGICallbackFinderFunc finder)
391
- {
392
- g_ptr_array_add(callback_finders, finder);
393
- }
394
-
395
- static gboolean
396
- source_func_p(GIArgInfo *info)
397
- {
398
- GITypeInfo type_info;
399
- GIBaseInfo *interface_info;
400
- GICallableInfo *callback_info;
401
- GITypeInfo return_type_info;
402
- GIArgInfo first_arg_info;
403
- GITypeInfo first_arg_type_info;
404
-
405
- g_arg_info_load_type(info, &type_info);
406
- if (g_type_info_get_tag(&type_info) != GI_TYPE_TAG_INTERFACE) {
407
- return FALSE;
408
- }
409
-
410
- interface_info = g_type_info_get_interface(&type_info);
411
- if (g_base_info_get_type(interface_info) != GI_INFO_TYPE_CALLBACK) {
412
- g_base_info_unref(interface_info);
413
- return FALSE;
414
- }
415
-
416
- callback_info = (GICallableInfo *)interface_info;
417
- g_callable_info_load_return_type(callback_info, &return_type_info);
418
- if (g_type_info_get_tag(&return_type_info) != GI_TYPE_TAG_BOOLEAN) {
419
- g_base_info_unref(interface_info);
420
- return FALSE;
421
- }
422
-
423
- if (g_callable_info_get_n_args(interface_info) != 1) {
424
- g_base_info_unref(interface_info);
425
- return FALSE;
426
- }
427
-
428
- g_callable_info_load_arg(interface_info, 0, &first_arg_info);
429
- g_arg_info_load_type(&first_arg_info, &first_arg_type_info);
430
- if (g_type_info_get_tag(&first_arg_type_info) != GI_TYPE_TAG_VOID) {
431
- g_base_info_unref(interface_info);
432
- return FALSE;
433
- }
434
-
435
- g_base_info_unref(interface_info);
436
- return TRUE;
437
- }
438
-
439
- static gboolean
440
- source_func_callback(gpointer user_data)
441
- {
442
- RBGICallbackData *callback_data = user_data;
443
- VALUE rb_keep;
444
- ID id_call;
445
-
446
- CONST_ID(id_call, "call");
447
- rb_keep = rb_funcall(callback_data->rb_callback, id_call, 0);
448
- if (callback_data->metadata->scope_type == GI_SCOPE_TYPE_ASYNC) {
449
- rb_gi_callback_data_free(callback_data);
450
- }
451
- return RVAL2CBOOL(rb_keep);
452
- }
453
-
454
- static gpointer
455
- source_func_callback_finder(GIArgInfo *arg_info)
456
- {
457
- if (!source_func_p(arg_info)) {
458
- return NULL;
459
- }
460
- return source_func_callback;
461
- }
462
-
463
- static void arguments_init(GArray **in_args,
464
- GArray **out_args,
465
- GPtrArray **args_metadata);
466
- static void arguments_free(VALUE rb_arguments,
467
- GArray *in_args,
468
- GArray *out_args,
469
- GPtrArray *args_metadata);
470
-
471
- static void
472
- argument_from_raw_data_interface(GICallableInfo *callable_info,
473
- void *raw_arg,
474
- GIArgument *argument,
475
- GITypeInfo *type_info)
476
- {
477
- GIBaseInfo *interface_info;
478
- GIInfoType interface_type;
479
-
480
- interface_info = g_type_info_get_interface(type_info);
481
- interface_type = g_base_info_get_type(interface_info);
482
-
483
- switch (interface_type) {
484
- case GI_INFO_TYPE_INVALID:
485
- case GI_INFO_TYPE_FUNCTION:
486
- case GI_INFO_TYPE_CALLBACK:
487
- rb_raise(rb_eNotImpError,
488
- "TODO: %s::%s: raw data -> GIArgument(interface)[%s]: <%s>",
489
- g_base_info_get_namespace(callable_info),
490
- g_base_info_get_name(callable_info),
491
- g_info_type_to_string(interface_type),
492
- g_base_info_get_name(interface_info));
493
- break;
494
- case GI_INFO_TYPE_STRUCT:
495
- argument->v_pointer = *((gpointer *)(raw_arg));
496
- break;
497
- case GI_INFO_TYPE_BOXED:
498
- case GI_INFO_TYPE_ENUM:
499
- rb_raise(rb_eNotImpError,
500
- "TODO: %s::%s: raw data -> GIArgument(interface)[%s]: <%s>",
501
- g_base_info_get_namespace(callable_info),
502
- g_base_info_get_name(callable_info),
503
- g_info_type_to_string(interface_type),
504
- g_base_info_get_name(interface_info));
505
- break;
506
- case GI_INFO_TYPE_FLAGS:
507
- argument->v_int32= *((gint32 *)(raw_arg));
508
- break;
509
- case GI_INFO_TYPE_OBJECT:
510
- case GI_INFO_TYPE_INTERFACE:
511
- argument->v_pointer = *((gpointer *)(raw_arg));
512
- break;
513
- case GI_INFO_TYPE_CONSTANT:
514
- rb_raise(rb_eNotImpError,
515
- "TODO: %s::%s: raw data -> GIArgument(interface)[%s]: <%s>",
516
- g_base_info_get_namespace(callable_info),
517
- g_base_info_get_name(callable_info),
518
- g_info_type_to_string(interface_type),
519
- g_base_info_get_name(interface_info));
520
- break;
521
- case GI_INFO_TYPE_INVALID_0:
522
- g_assert_not_reached();
523
- break;
524
- case GI_INFO_TYPE_UNION:
525
- case GI_INFO_TYPE_VALUE:
526
- case GI_INFO_TYPE_SIGNAL:
527
- case GI_INFO_TYPE_VFUNC:
528
- case GI_INFO_TYPE_PROPERTY:
529
- case GI_INFO_TYPE_FIELD:
530
- case GI_INFO_TYPE_ARG:
531
- case GI_INFO_TYPE_TYPE:
532
- case GI_INFO_TYPE_UNRESOLVED:
533
- default:
534
- rb_raise(rb_eNotImpError,
535
- "TODO: %s::%s: raw data -> GIArgument(interface)[%s]: <%s>",
536
- g_base_info_get_namespace(callable_info),
537
- g_base_info_get_name(callable_info),
538
- g_info_type_to_string(interface_type),
539
- g_base_info_get_name(interface_info));
540
- break;
541
- }
542
-
543
- g_base_info_unref(interface_info);
544
- }
545
-
546
- static void
547
- argument_from_raw_data(GICallableInfo *callable_info,
548
- void **raw_args,
549
- GArray *in_args,
550
- GArray *out_args,
551
- GPtrArray *args_metadata,
552
- guint i)
553
- {
554
- RBGIArgMetadata *metadata;
555
- GIArgument *argument;
556
- GITypeInfo *type_info;
557
- GITypeTag type_tag;
558
-
559
- metadata = g_ptr_array_index(args_metadata, i);
560
-
561
- if (metadata->direction == GI_DIRECTION_INOUT) {
562
- argument = &g_array_index(in_args, GIArgument, metadata->in_arg_index);
563
- argument->v_pointer = *((gpointer *)(raw_args[i]));
564
- return;
565
- } else if (metadata->direction == GI_DIRECTION_OUT) {
566
- argument = &g_array_index(out_args, GIArgument, metadata->out_arg_index);
567
- argument->v_pointer = *((gpointer *)(raw_args[i]));
568
- return;
569
- }
570
-
571
- argument = &g_array_index(in_args, GIArgument, metadata->in_arg_index);
572
- type_info = g_arg_info_get_type(&(metadata->arg_info));
573
- type_tag = g_type_info_get_tag(type_info);
574
-
575
- switch (type_tag) {
576
- case GI_TYPE_TAG_VOID:
577
- argument->v_pointer = *((gpointer *)(raw_args[i]));
578
- break;
579
- case GI_TYPE_TAG_BOOLEAN:
580
- argument->v_boolean = *((gboolean *)(raw_args[i]));
581
- break;
582
- case GI_TYPE_TAG_INT8:
583
- argument->v_int8 = *((gint8 *)(raw_args[i]));
584
- break;
585
- case GI_TYPE_TAG_UINT8:
586
- argument->v_uint8 = *((guint8 *)(raw_args[i]));
587
- break;
588
- case GI_TYPE_TAG_INT16:
589
- argument->v_int16 = *((gint16 *)(raw_args[i]));
590
- break;
591
- case GI_TYPE_TAG_UINT16:
592
- argument->v_uint16 = *((guint16 *)(raw_args[i]));
593
- break;
594
- case GI_TYPE_TAG_INT32:
595
- argument->v_int32 = *((gint32 *)(raw_args[i]));
596
- break;
597
- case GI_TYPE_TAG_UINT32:
598
- argument->v_uint32 = *((guint32 *)(raw_args[i]));
599
- break;
600
- case GI_TYPE_TAG_INT64:
601
- argument->v_int64 = *((gint64 *)(raw_args[i]));
602
- break;
603
- case GI_TYPE_TAG_UINT64:
604
- argument->v_uint64 = *((guint64 *)(raw_args[i]));
605
- break;
606
- case GI_TYPE_TAG_FLOAT:
607
- argument->v_float = *((gfloat *)(raw_args[i]));
608
- break;
609
- case GI_TYPE_TAG_DOUBLE:
610
- argument->v_double = *((gdouble *)(raw_args[i]));
611
- break;
612
- case GI_TYPE_TAG_GTYPE:
613
- argument->v_size = *((gsize *)(raw_args[i]));
614
- break;
615
- case GI_TYPE_TAG_UTF8:
616
- case GI_TYPE_TAG_FILENAME:
617
- argument->v_string = *((gchar **)(raw_args[i]));
618
- break;
619
- case GI_TYPE_TAG_ARRAY:
620
- argument->v_pointer = *((gpointer *)(raw_args[i]));
621
- break;
622
- case GI_TYPE_TAG_INTERFACE:
623
- argument_from_raw_data_interface(callable_info,
624
- raw_args[i],
625
- argument,
626
- type_info);
627
- break;
628
- case GI_TYPE_TAG_GLIST:
629
- case GI_TYPE_TAG_GSLIST:
630
- case GI_TYPE_TAG_GHASH:
631
- argument->v_pointer = *((gpointer *)(raw_args[i]));
632
- break;
633
- case GI_TYPE_TAG_ERROR:
634
- argument->v_pointer = *((GError **)(raw_args[i]));
635
- break;
636
- case GI_TYPE_TAG_UNICHAR:
637
- argument->v_uint32 = *((gunichar *)(raw_args[i]));
638
- break;
639
- default:
640
- g_assert_not_reached();
641
- break;
642
- }
643
-
644
- g_base_info_unref(type_info);
645
- }
646
-
647
- static void
648
- arguments_from_raw_data(GICallableInfo *callable_info,
649
- void **args,
650
- GArray *in_args,
651
- GArray *out_args,
652
- GPtrArray *args_metadata)
653
- {
654
- guint i;
655
-
656
- for (i = 0; i < args_metadata->len; i++) {
657
- argument_from_raw_data(callable_info,
658
- args,
659
- in_args,
660
- out_args,
661
- args_metadata,
662
- i);
663
- }
664
- }
665
-
666
- static void
667
- in_arguments_to_ruby(GArray *in_args,
668
- GArray *out_args,
669
- GPtrArray *args_metadata,
670
- GArray *rb_args)
671
- {
672
- guint i;
673
-
674
- for (i = 0; i < args_metadata->len; i++) {
675
- RBGIArgMetadata *metadata;
676
- GIArgument *argument;
677
- GITypeInfo *type_info;
678
- VALUE rb_arg;
679
-
680
- metadata = g_ptr_array_index(args_metadata, i);
681
-
682
- if (metadata->direction == GI_DIRECTION_OUT) {
683
- continue;
684
- }
685
- if (metadata->closure_p) {
686
- continue;
687
- }
688
-
689
- argument = &g_array_index(in_args, GIArgument, metadata->in_arg_index);
690
- type_info = g_arg_info_get_type(&(metadata->arg_info));
691
- rb_arg = GI_ARGUMENT2RVAL(argument,
692
- FALSE,
693
- type_info,
694
- in_args,
695
- out_args,
696
- args_metadata);
697
- g_array_append_val(rb_args, rb_arg);
698
- }
699
- }
700
-
701
- static void
702
- out_argument_to_raw_data_interface(GICallableInfo *callable_info,
703
- GIArgument *argument,
704
- gpointer result,
705
- GITypeInfo *type_info,
706
- G_GNUC_UNUSED GITransfer transfer /* TODO */,
707
- gboolean is_return_value)
708
- {
709
- GIBaseInfo *interface_info;
710
- GIInfoType interface_type;
711
- GIFFIReturnValue *ffi_return_value = result;
712
-
713
- interface_info = g_type_info_get_interface(type_info);
714
- interface_type = g_base_info_get_type(interface_info);
715
-
716
- switch (interface_type) {
717
- case GI_INFO_TYPE_INVALID:
718
- case GI_INFO_TYPE_FUNCTION:
719
- case GI_INFO_TYPE_CALLBACK:
720
- case GI_INFO_TYPE_STRUCT:
721
- case GI_INFO_TYPE_BOXED:
722
- rb_raise(rb_eNotImpError,
723
- "TODO: %s::%s: out raw data(interface)[%s]: <%s>",
724
- g_base_info_get_namespace(callable_info),
725
- g_base_info_get_name(callable_info),
726
- g_info_type_to_string(interface_type),
727
- g_base_info_get_name(interface_info));
728
- break;
729
- case GI_INFO_TYPE_ENUM:
730
- if (is_return_value) {
731
- ffi_return_value->v_ulong = argument->v_int;
732
- } else {
733
- *((gint *)result) = argument->v_int;
734
- }
735
- break;
736
- case GI_INFO_TYPE_FLAGS:
737
- case GI_INFO_TYPE_OBJECT:
738
- case GI_INFO_TYPE_INTERFACE:
739
- case GI_INFO_TYPE_CONSTANT:
740
- rb_raise(rb_eNotImpError,
741
- "TODO: %s::%s: out raw data(interface)[%s]: <%s>",
742
- g_base_info_get_namespace(callable_info),
743
- g_base_info_get_name(callable_info),
744
- g_info_type_to_string(interface_type),
745
- g_base_info_get_name(interface_info));
746
- break;
747
- case GI_INFO_TYPE_INVALID_0:
748
- g_assert_not_reached();
749
- break;
750
- case GI_INFO_TYPE_UNION:
751
- case GI_INFO_TYPE_VALUE:
752
- case GI_INFO_TYPE_SIGNAL:
753
- case GI_INFO_TYPE_VFUNC:
754
- case GI_INFO_TYPE_PROPERTY:
755
- case GI_INFO_TYPE_FIELD:
756
- case GI_INFO_TYPE_ARG:
757
- case GI_INFO_TYPE_TYPE:
758
- case GI_INFO_TYPE_UNRESOLVED:
759
- default:
760
- rb_raise(rb_eNotImpError,
761
- "TODO: %s::%s: out raw data(interface)[%s]: <%s>",
762
- g_base_info_get_namespace(callable_info),
763
- g_base_info_get_name(callable_info),
764
- g_info_type_to_string(interface_type),
765
- g_base_info_get_name(interface_info));
766
- break;
767
- }
768
-
769
- g_base_info_unref(interface_info);
770
- }
771
-
772
- /*
773
- We need to cast from different type for return value. (We don't
774
- need it for out arguments.) Because of libffi specification:
775
-
776
- https://github.com/libffi/libffi/blob/master/doc/libffi.texi#L190
777
-
778
- @var{rvalue} is a pointer to a chunk of memory that will hold the
779
- result of the function call. This must be large enough to hold the
780
- result, no smaller than the system register size (generally 32 or 64
781
- bits), and must be suitably aligned; it is the caller's responsibility
782
- to ensure this. If @var{cif} declares that the function returns
783
- @code{void} (using @code{ffi_type_void}), then @var{rvalue} is
784
- ignored.
785
-
786
- https://github.com/libffi/libffi/blob/master/doc/libffi.texi#L198
787
-
788
- In most situations, @samp{libffi} will handle promotion according to
789
- the ABI. However, for historical reasons, there is a special case
790
- with return values that must be handled by your code. In particular,
791
- for integral (not @code{struct}) types that are narrower than the
792
- system register size, the return value will be widened by
793
- @samp{libffi}. @samp{libffi} provides a type, @code{ffi_arg}, that
794
- can be used as the return type. For example, if the CIF was defined
795
- with a return type of @code{char}, @samp{libffi} will try to store a
796
- full @code{ffi_arg} into the return value.
797
-
798
- See also:
799
- * https://github.com/ruby-gnome2/ruby-gnome2/issues/758#issuecomment-243149237
800
- * https://github.com/libffi/libffi/pull/216
801
-
802
- This ffi_return_value case implementation is based on
803
- gi_type_info_extract_ffi_return_value().
804
- */
805
- static void
806
- out_argument_to_raw_data(GICallableInfo *callable_info,
807
- VALUE rb_result,
808
- gpointer result,
809
- GITypeInfo *type_info,
810
- GITransfer transfer,
811
- gboolean is_return_value)
812
- {
813
- GIArgument argument;
814
- GITypeTag type_tag;
815
- GIFFIReturnValue *ffi_return_value = result;
816
-
817
- rb_gi_value_argument_from_ruby(&argument,
818
- type_info,
819
- rb_result,
820
- rb_result);
821
- type_tag = g_type_info_get_tag(type_info);
822
- switch (type_tag) {
823
- case GI_TYPE_TAG_VOID:
824
- g_assert_not_reached();
825
- break;
826
- case GI_TYPE_TAG_BOOLEAN:
827
- if (is_return_value) {
828
- ffi_return_value->v_ulong = argument.v_boolean;
829
- } else {
830
- *((gboolean *)result) = argument.v_boolean;
831
- }
832
- break;
833
- case GI_TYPE_TAG_INT8:
834
- if (is_return_value) {
835
- ffi_return_value->v_long = argument.v_int8;
836
- } else {
837
- *((gint8 *)result) = argument.v_int8;
838
- }
839
- break;
840
- case GI_TYPE_TAG_UINT8:
841
- if (is_return_value) {
842
- ffi_return_value->v_ulong = argument.v_uint8;
843
- } else {
844
- *((guint8 *)result) = argument.v_uint8;
845
- }
846
- break;
847
- case GI_TYPE_TAG_INT16:
848
- if (is_return_value) {
849
- ffi_return_value->v_long = argument.v_int16;
850
- } else {
851
- *((gint16 *)result) = argument.v_int16;
852
- }
853
- break;
854
- case GI_TYPE_TAG_UINT16:
855
- if (is_return_value) {
856
- ffi_return_value->v_ulong = argument.v_uint16;
857
- } else {
858
- *((guint16 *)result) = argument.v_uint16;
859
- }
860
- break;
861
- case GI_TYPE_TAG_INT32:
862
- if (is_return_value) {
863
- ffi_return_value->v_long = argument.v_int32;
864
- } else {
865
- *((gint32 *)result) = argument.v_int32;
866
- }
867
- break;
868
- case GI_TYPE_TAG_UINT32:
869
- if (is_return_value) {
870
- ffi_return_value->v_ulong = argument.v_uint32;
871
- } else {
872
- *((guint32 *)result) = argument.v_uint32;
873
- }
874
- break;
875
- case GI_TYPE_TAG_INT64:
876
- *((gint64 *)result) = argument.v_int64;
877
- break;
878
- case GI_TYPE_TAG_UINT64:
879
- *((guint64 *)result) = argument.v_uint64;
880
- break;
881
- case GI_TYPE_TAG_FLOAT:
882
- *((gfloat *)result) = argument.v_float;
883
- break;
884
- case GI_TYPE_TAG_DOUBLE:
885
- *((gdouble *)result) = argument.v_double;
886
- break;
887
- case GI_TYPE_TAG_GTYPE:
888
- if (is_return_value) {
889
- ffi_return_value->v_ulong = argument.v_size;
890
- } else {
891
- *((gsize *)result) = argument.v_size;
892
- }
893
- break;
894
- case GI_TYPE_TAG_UTF8:
895
- case GI_TYPE_TAG_FILENAME:
896
- if (is_return_value) {
897
- ffi_return_value->v_ulong = (gulong)(argument.v_string);
898
- } else {
899
- *((gchar **)result) = argument.v_string;
900
- }
901
- break;
902
- case GI_TYPE_TAG_ARRAY:
903
- if (is_return_value) {
904
- ffi_return_value->v_ulong = (gulong)(argument.v_pointer);
905
- } else {
906
- *((gpointer *)result) = argument.v_pointer;
907
- }
908
- break;
909
- case GI_TYPE_TAG_INTERFACE:
910
- out_argument_to_raw_data_interface(callable_info,
911
- &argument,
912
- result,
913
- type_info,
914
- transfer,
915
- is_return_value);
916
- break;
917
- case GI_TYPE_TAG_GLIST:
918
- case GI_TYPE_TAG_GSLIST:
919
- case GI_TYPE_TAG_GHASH:
920
- if (is_return_value) {
921
- ffi_return_value->v_ulong = (gulong)(argument.v_pointer);
922
- } else {
923
- *((gpointer *)result) = argument.v_pointer;
924
- }
925
- break;
926
- case GI_TYPE_TAG_ERROR:
927
- if (is_return_value) {
928
- ffi_return_value->v_ulong = (gulong)(argument.v_pointer);
929
- } else {
930
- *((GError **)result) = argument.v_pointer;
931
- }
932
- break;
933
- case GI_TYPE_TAG_UNICHAR:
934
- if (is_return_value) {
935
- ffi_return_value->v_ulong = argument.v_uint32;
936
- } else {
937
- *((gunichar *)result) = argument.v_uint32;
938
- }
939
- break;
940
- default:
941
- g_assert_not_reached();
942
- break;
943
- }
944
- }
945
-
946
- static void
947
- out_arguments_to_raw_data(GICallableInfo *callable_info,
948
- VALUE rb_results,
949
- void *result,
950
- GArray *out_args,
951
- GPtrArray *args_metadata)
952
- {
953
- int i_rb_result = 0;
954
- guint i;
955
- GITypeInfo *return_type_info;
956
- GITypeTag return_type_tag;
957
-
958
- return_type_info = g_callable_info_get_return_type(callable_info);
959
- return_type_tag = g_type_info_get_tag(return_type_info);
960
- if (return_type_tag != GI_TYPE_TAG_VOID) {
961
- GITransfer transfer;
962
- transfer = g_callable_info_get_caller_owns(callable_info);
963
- if (out_args->len == 0) {
964
- VALUE rb_return_value = rb_results;
965
- out_argument_to_raw_data(callable_info,
966
- rb_return_value,
967
- result,
968
- return_type_info,
969
- transfer,
970
- TRUE);
971
- } else {
972
- out_argument_to_raw_data(callable_info,
973
- RARRAY_AREF(rb_results, i_rb_result),
974
- result,
975
- return_type_info,
976
- transfer,
977
- TRUE);
978
- i_rb_result++;
979
- }
980
- }
981
- g_base_info_unref(return_type_info);
982
-
983
- for (i = 0; i < args_metadata->len; i++) {
984
- RBGIArgMetadata *metadata;
985
- GIArgument *argument;
986
- GITypeInfo *type_info;
987
- GITransfer transfer;
988
-
989
- metadata = g_ptr_array_index(args_metadata, i);
990
-
991
- /* TODO: support GI_DIRECTION_INOUT */
992
- if (metadata->direction != GI_DIRECTION_OUT) {
993
- continue;
994
- }
995
-
996
- argument = &g_array_index(out_args, GIArgument, metadata->out_arg_index);
997
- type_info = g_arg_info_get_type(&(metadata->arg_info));
998
- transfer = g_arg_info_get_ownership_transfer(&(metadata->arg_info));
999
- out_argument_to_raw_data(callable_info,
1000
- RARRAY_AREF(rb_results, i_rb_result),
1001
- argument->v_pointer,
1002
- type_info,
1003
- transfer,
1004
- FALSE);
1005
- i_rb_result++;
1006
- g_base_info_unref(type_info);
1007
- }
1008
- }
1009
-
1010
- static void
1011
- ffi_closure_callback(G_GNUC_UNUSED ffi_cif *cif,
1012
- void *result,
1013
- void **raw_args,
1014
- void *data)
1015
- {
1016
- RBGICallback *callback = data;
1017
- RBGICallbackData *callback_data = NULL;
1018
- GArray *in_args;
1019
- GArray *out_args;
1020
- GPtrArray *args_metadata;
1021
- VALUE rb_results;
1022
-
1023
- arguments_init(&in_args, &out_args, &args_metadata);
1024
- allocate_arguments(callback->callback_info,
1025
- in_args,
1026
- out_args,
1027
- args_metadata);
1028
- fill_metadata(args_metadata, callback->callback_info);
1029
- arguments_from_raw_data(callback->callback_info,
1030
- raw_args,
1031
- in_args,
1032
- out_args,
1033
- args_metadata);
1034
-
1035
- {
1036
- guint i;
1037
-
1038
- for (i = 0; i < args_metadata->len; i++) {
1039
- RBGIArgMetadata *metadata;
1040
-
1041
- metadata = g_ptr_array_index(args_metadata, i);
1042
- if (!metadata->closure_p) {
1043
- continue;
1044
- }
1045
-
1046
- callback_data = *((RBGICallbackData **)(raw_args[i]));
1047
- break;
1048
- }
1049
-
1050
- if (!callback_data && args_metadata->len > 0) {
1051
- RBGIArgMetadata *metadata;
1052
- GIArgInfo *arg_info;
1053
- GITypeInfo *type_info;
1054
- GITypeTag type_tag;
1055
- gboolean is_pointer;
1056
- const gchar *arg_name;
1057
-
1058
- i = args_metadata->len - 1;
1059
- metadata = g_ptr_array_index(args_metadata, i);
1060
- arg_info = &(metadata->arg_info);
1061
- type_info = g_arg_info_get_type(arg_info);
1062
- type_tag = g_type_info_get_tag(type_info);
1063
- is_pointer = g_type_info_is_pointer(type_info);
1064
- g_base_info_unref(type_info);
1065
- arg_name = g_base_info_get_name(arg_info);
1066
- if (type_tag == GI_TYPE_TAG_VOID &&
1067
- is_pointer &&
1068
- strcmp(arg_name, "data") == 0) {
1069
- callback_data = *((RBGICallbackData **)(raw_args[i]));
1070
- }
1071
- }
1072
- }
1073
-
1074
- {
1075
- ID id_call;
1076
- GArray *rb_args;
1077
-
1078
- rb_args = g_array_new(FALSE, FALSE, sizeof(VALUE));
1079
- in_arguments_to_ruby(in_args,
1080
- out_args,
1081
- args_metadata,
1082
- rb_args);
1083
- CONST_ID(id_call, "call");
1084
- /* TODO: use rb_protect() */
1085
- rb_results = rb_funcallv(callback_data->rb_callback,
1086
- id_call,
1087
- rb_args->len,
1088
- (VALUE *)(void *)(rb_args->data));
1089
- g_array_free(rb_args, TRUE);
1090
- }
1091
-
1092
- out_arguments_to_raw_data(callback->callback_info,
1093
- rb_results,
1094
- result,
1095
- out_args,
1096
- args_metadata);
1097
-
1098
- if (callback_data->metadata->scope_type == GI_SCOPE_TYPE_ASYNC) {
1099
- rb_gi_callback_data_free(callback_data);
1100
- }
1101
- }
1102
-
1103
- static void
1104
- in_callback_argument_from_ruby(RBGIArgMetadata *metadata,
1105
- GArray *in_args,
1106
- VALUE self,
1107
- VALUE rb_arguments)
1108
- {
1109
- gpointer callback_function;
1110
- GIArgInfo *arg_info;
1111
- GIArgument *callback_argument;
1112
- GIArgument *closure_argument = NULL;
1113
- GIArgument *destroy_argument = NULL;
1114
- RBGICallback *callback = NULL;
1115
-
1116
- arg_info = &(metadata->arg_info);
1117
-
1118
- callback_argument = &(g_array_index(in_args,
1119
- GIArgument,
1120
- metadata->in_arg_index));
1121
- if (metadata->closure_in_arg_index != -1) {
1122
- closure_argument = &(g_array_index(in_args,
1123
- GIArgument,
1124
- metadata->closure_in_arg_index));
1125
- }
1126
- if (metadata->destroy_in_arg_index != -1) {
1127
- destroy_argument = &(g_array_index(in_args,
1128
- GIArgument,
1129
- metadata->destroy_in_arg_index));
1130
- }
1131
-
1132
- if (!rb_block_given_p() && g_arg_info_may_be_null(arg_info)) {
1133
- callback_argument->v_pointer = NULL;
1134
- if (closure_argument) {
1135
- closure_argument->v_pointer = NULL;
1136
- }
1137
- if (destroy_argument) {
1138
- destroy_argument->v_pointer = NULL;
1139
- }
1140
- return;
1141
- }
1142
-
1143
- callback_function = find_callback_function(arg_info);
1144
- if (callback_function) {
1145
- callback_argument->v_pointer = callback_function;
1146
- } else {
1147
- callback = RB_ZALLOC(RBGICallback);
1148
- callback->type_info = g_arg_info_get_type(arg_info);
1149
- callback->callback_info = g_type_info_get_interface(callback->type_info);
1150
- callback->closure =
1151
- g_callable_info_prepare_closure(callback->callback_info,
1152
- &(callback->cif),
1153
- ffi_closure_callback,
1154
- callback);
1155
- callback_argument->v_pointer = callback->closure;
1156
- }
1157
-
1158
- if (closure_argument) {
1159
- RBGICallbackData *callback_data;
1160
- VALUE rb_owner = self;
1161
- static VALUE mGLibObject = Qnil;
1162
-
1163
- if (rb_gi_is_debug_mode()) {
1164
- GICallableInfo *callable_info = metadata->callable_info;
1165
- g_print("[rb-gi] callback: %s::%s()\n",
1166
- g_base_info_get_namespace(callable_info),
1167
- g_base_info_get_name(callable_info));
1168
- rb_p(rb_ary_new_from_args(2, self, rb_arguments));
1169
- }
1170
-
1171
- callback_data = ALLOC(RBGICallbackData);
1172
- callback_data->callback = callback;
1173
- callback_data->metadata = metadata;
1174
- callback_data->rb_callback = rb_block_proc();
1175
- if (NIL_P(mGLibObject)) {
1176
- mGLibObject = rb_const_get(mGLib, rb_intern("Object"));
1177
- }
1178
- if (NIL_P(rb_owner)) {
1179
- /* Module function case. */
1180
- VALUE rb_first_argument = rb_ary_entry(rb_arguments, 0);
1181
- if (rb_obj_is_kind_of(rb_first_argument, mGLibObject)) {
1182
- /* If the first argument of the module function call is
1183
- GObject, it's suitable for owner.
1184
- For example: pango_cairo_context_set_shape_renderer() */
1185
- rb_owner = rb_first_argument;
1186
- }
1187
- }
1188
- if (rb_obj_is_kind_of(rb_owner, mGLibObject)) {
1189
- rbgobj_object_add_relative(rb_owner, callback_data->rb_callback);
1190
- callback_data->owner = RVAL2GOBJ(rb_owner);
1191
- g_object_weak_ref(callback_data->owner,
1192
- rb_gi_callback_data_weak_notify,
1193
- callback_data);
1194
- callback_data->rb_owner = Qnil;
1195
- } else {
1196
- /* Callback is GC-ed only when callback is invalidated. */
1197
- if (NIL_P(rb_owner)) {
1198
- /* Module function case. */
1199
- static VALUE rb_mGI = Qnil;
1200
- if (NIL_P(rb_mGI)) {
1201
- rb_mGI = rb_const_get(rb_cObject,
1202
- rb_intern("GObjectIntrospection"));
1203
- }
1204
- rbgobj_add_relative(rb_mGI, callback_data->rb_callback);
1205
- callback_data->rb_owner = rb_mGI;
1206
- } else {
1207
- /* Class method case. */
1208
- rbgobj_add_relative(rb_owner, callback_data->rb_callback);
1209
- callback_data->rb_owner = rb_owner;
1210
- }
1211
- callback_data->owner = NULL;
1212
- }
1213
- closure_argument->v_pointer = callback_data;
1214
- }
1215
-
1216
- if (destroy_argument) {
1217
- destroy_argument->v_pointer = rb_gi_callback_data_destroy_notify;
1218
- }
1219
- }
1220
-
1221
- static void
1222
- in_argument_from_ruby(GICallableInfo *callable_info,
1223
- RBGIArgMetadata *metadata,
1224
- VALUE rb_arguments,
1225
- GArray *in_args,
1226
- GPtrArray *args_metadata,
1227
- VALUE self)
1228
- {
1229
- if (metadata->callback_p && !metadata->destroy_p) {
1230
- in_callback_argument_from_ruby(metadata, in_args, self, rb_arguments);
1231
- return;
1232
- }
1233
-
1234
- if (metadata->rb_arg_index == -1) {
1235
- return;
1236
- }
1237
-
1238
- if (metadata->array_p) {
1239
- GIArgument *array_argument;
1240
- GIArgument *length_argument = NULL;
1241
- GIArgInfo *length_arg_info = NULL;
1242
- VALUE rb_argument = Qnil;
1243
-
1244
- if (RARRAY_LEN(rb_arguments) > metadata->rb_arg_index) {
1245
- rb_argument = RARRAY_PTR(rb_arguments)[metadata->rb_arg_index];
1246
- }
1247
- array_argument = &(g_array_index(in_args,
1248
- GIArgument,
1249
- metadata->in_arg_index));
1250
- if (metadata->array_length_in_arg_index != -1) {
1251
- RBGIArgMetadata *length_metadata;
1252
- length_argument =
1253
- &(g_array_index(in_args,
1254
- GIArgument,
1255
- metadata->array_length_in_arg_index));
1256
- length_metadata =
1257
- g_ptr_array_index(args_metadata,
1258
- metadata->array_length_arg_index);
1259
- length_arg_info = &(length_metadata->arg_info);
1260
- }
1261
- RVAL2GI_IN_ARRAY_ARGUMENT(array_argument,
1262
- length_argument,
1263
- &(metadata->arg_info),
1264
- length_arg_info,
1265
- rb_argument);
1266
- } else {
1267
- GIArgument *argument;
1268
- VALUE rb_argument = Qnil;
1269
-
1270
- if (RARRAY_LEN(rb_arguments) > metadata->rb_arg_index) {
1271
- rb_argument = RARRAY_PTR(rb_arguments)[metadata->rb_arg_index];
1272
- }
1273
- argument = &(g_array_index(in_args, GIArgument, metadata->in_arg_index));
1274
- rb_gi_in_argument_from_ruby(callable_info,
1275
- argument,
1276
- &(metadata->arg_info),
1277
- metadata->rb_arg_index,
1278
- rb_argument,
1279
- self);
1280
- }
1281
- }
1282
-
1283
- static void
1284
- out_argument_from_ruby(RBGIArgMetadata *metadata, GArray *out_args)
1285
- {
1286
- GIArgument *argument;
1287
-
1288
- argument = &(g_array_index(out_args, GIArgument, metadata->out_arg_index));
1289
- rb_gi_out_argument_init(argument, &(metadata->arg_info));
1290
- }
1291
-
1292
- static void
1293
- arg_metadata_free(gpointer data)
1294
- {
1295
- RBGIArgMetadata *metadata = data;
1296
- if (metadata->scope_type == GI_SCOPE_TYPE_ASYNC ||
1297
- metadata->scope_type == GI_SCOPE_TYPE_NOTIFIED) {
1298
- return;
1299
- }
1300
- xfree(metadata);
1301
- }
1302
-
1303
- static void
1304
- arguments_from_ruby(GICallableInfo *info, VALUE self, VALUE rb_arguments,
1305
- GArray *in_args, GArray *out_args,
1306
- GPtrArray *args_metadata)
1307
- {
1308
- gint i, n_args;
1309
-
1310
- allocate_arguments(info, in_args, out_args, args_metadata);
1311
- fill_metadata(args_metadata, info);
1312
-
1313
- n_args = g_callable_info_get_n_args(info);
1314
- for (i = 0; i < n_args; i++) {
1315
- RBGIArgMetadata *metadata;
1316
-
1317
- metadata = g_ptr_array_index(args_metadata, i);
1318
- if (metadata->in_arg_index != -1) {
1319
- in_argument_from_ruby(info,
1320
- metadata,
1321
- rb_arguments,
1322
- in_args,
1323
- args_metadata,
1324
- self);
1325
- } else {
1326
- out_argument_from_ruby(metadata, out_args);
1327
- }
1328
- }
1329
- }
1330
-
1331
- static VALUE
1332
- out_arguments_to_ruby(GICallableInfo *callable_info,
1333
- GArray *in_args, GArray *out_args,
1334
- GPtrArray *args_metadata)
1335
- {
1336
- gint i, n_args;
1337
- VALUE rb_out_args;
1338
-
1339
- rb_out_args = rb_ary_new();
1340
- n_args = g_callable_info_get_n_args(callable_info);
1341
- for (i = 0; i < n_args; i++) {
1342
- RBGIArgMetadata *metadata;
1343
- GIArgument *argument = NULL;
1344
- VALUE rb_argument;
1345
-
1346
- metadata = g_ptr_array_index(args_metadata, i);
1347
- if (metadata->array_length_p) {
1348
- continue;
1349
- }
1350
-
1351
- switch (metadata->direction) {
1352
- case GI_DIRECTION_IN:
1353
- break;
1354
- case GI_DIRECTION_OUT:
1355
- argument = &g_array_index(out_args, GIArgument,
1356
- metadata->out_arg_index);
1357
- break;
1358
- case GI_DIRECTION_INOUT:
1359
- argument = &g_array_index(in_args, GIArgument,
1360
- metadata->in_arg_index);
1361
- break;
1362
- default:
1363
- g_assert_not_reached();
1364
- break;
1365
- }
1366
-
1367
- if (!argument) {
1368
- continue;
1369
- }
1370
-
1371
- rb_argument = GI_OUT_ARGUMENT2RVAL(argument,
1372
- &(metadata->arg_info),
1373
- in_args,
1374
- out_args,
1375
- args_metadata);
1376
- rb_ary_push(rb_out_args, rb_argument);
1377
- }
1378
-
1379
- if (RARRAY_LEN(rb_out_args) == 0) {
1380
- return Qnil;
1381
- } else {
1382
- return rb_out_args;
1383
- }
1384
- }
1385
-
1386
- static void
1387
- arguments_init(GArray **in_args, GArray **out_args, GPtrArray **args_metadata)
1388
- {
1389
- *in_args = g_array_new(FALSE, FALSE, sizeof(GIArgument));
1390
- *out_args = g_array_new(FALSE, FALSE, sizeof(GIArgument));
1391
- *args_metadata = g_ptr_array_new_with_free_func(arg_metadata_free);
1392
- }
1393
-
1394
- static void
1395
- arguments_free(VALUE rb_arguments,
1396
- GArray *in_args, GArray *out_args, GPtrArray *args_metadata)
1397
- {
1398
- guint i;
1399
-
1400
- for (i = 0; i < args_metadata->len; i++) {
1401
- RBGIArgMetadata *metadata;
1402
- gint in_arg_index;
1403
-
1404
- metadata = g_ptr_array_index(args_metadata, i);
1405
- if (metadata->direction == GI_DIRECTION_IN ||
1406
- metadata->direction == GI_DIRECTION_INOUT) {
1407
- in_arg_index = metadata->in_arg_index;
1408
- if (in_arg_index != -1) {
1409
- gint rb_arg_index;
1410
- VALUE rb_argument = Qnil;
1411
- GIArgument *argument;
1412
-
1413
- rb_arg_index = metadata->rb_arg_index;
1414
- if (RARRAY_LEN(rb_arguments) > rb_arg_index) {
1415
- rb_argument = RARRAY_PTR(rb_arguments)[rb_arg_index];
1416
- }
1417
- argument = &(g_array_index(in_args, GIArgument, in_arg_index));
1418
- rb_gi_in_argument_free(rb_argument,
1419
- argument,
1420
- &(metadata->arg_info));
1421
- }
1422
- } else {
1423
- GIArgument *argument;
1424
- argument = &(g_array_index(out_args, GIArgument,
1425
- metadata->out_arg_index));
1426
- rb_gi_out_argument_fin(argument, &(metadata->arg_info));
1427
- }
1428
- }
1429
-
1430
- g_array_unref(in_args);
1431
- g_array_unref(out_args);
1432
- g_ptr_array_unref(args_metadata);
1433
- }
1434
-
1435
102
  typedef struct {
1436
103
  GIFunctionInfo *info;
1437
104
  GArray *in_args;
@@ -1464,25 +131,6 @@ rb_gi_function_info_invoke_raw_call_without_gvl_body(void *user_data)
1464
131
  return RB_THREAD_CALL_WITHOUT_GVL_FUNC_RETURN_VALUE;
1465
132
  }
1466
133
 
1467
- static gboolean
1468
- gobject_based_p(GIBaseInfo *info)
1469
- {
1470
- GIBaseInfo *container_info;
1471
- GIRegisteredTypeInfo *registered_type_info;
1472
-
1473
- container_info = g_base_info_get_container(info);
1474
- if (g_base_info_get_type(container_info) != GI_INFO_TYPE_STRUCT) {
1475
- return TRUE;
1476
- }
1477
-
1478
- registered_type_info = (GIRegisteredTypeInfo *)container_info;
1479
- if (g_registered_type_info_get_type_init(registered_type_info)) {
1480
- return TRUE;
1481
- }
1482
-
1483
- return FALSE;
1484
- }
1485
-
1486
134
  VALUE
1487
135
  rb_gi_function_info_invoke_raw(GIFunctionInfo *info,
1488
136
  VALUE rb_info,
@@ -1492,48 +140,26 @@ rb_gi_function_info_invoke_raw(GIFunctionInfo *info,
1492
140
  VALUE *rb_return_value)
1493
141
  {
1494
142
  GICallableInfo *callable_info;
1495
- GIArgument receiver;
1496
- GArray *in_args, *out_args;
1497
- GPtrArray *args_metadata;
143
+ RBGIArguments args;
1498
144
  VALUE rb_out_args = Qnil;
1499
145
  gboolean succeeded;
1500
146
  GError *error = NULL;
1501
147
  gboolean unlock_gvl = FALSE;
1502
- gboolean rb_receiver_is_class = FALSE;
1503
148
 
1504
149
  unlock_gvl = RVAL2CBOOL(rb_funcall(rb_info, rb_intern("unlock_gvl?"), 0));
1505
- if (NIL_P(rb_receiver)) {
1506
- receiver.v_pointer = NULL;
1507
- } else {
1508
- VALUE rb_receiver_class;
1509
- rb_receiver_class = rb_class_of(rb_receiver);
1510
- if (gobject_based_p((GIBaseInfo *)info) ||
1511
- rb_respond_to(rb_receiver_class, rb_intern("gtype"))) {
1512
- receiver.v_pointer = RVAL2GOBJ(rb_receiver);
1513
- } else if (RVAL2CBOOL(rb_obj_is_kind_of(rb_receiver, rb_cClass)) &&
1514
- rb_respond_to(rb_receiver, rb_intern("gtype"))) {
1515
- GObjectClass *object_class;
1516
- rb_receiver_is_class = TRUE;
1517
- object_class = g_type_class_ref(CLASS2GTYPE(rb_receiver));
1518
- receiver.v_pointer = object_class;
1519
- } else {
1520
- receiver.v_pointer = rb_gi_struct_get_raw(rb_receiver, G_TYPE_NONE);
1521
- }
1522
- }
1523
150
  rb_arguments = rbg_to_array(rb_arguments);
1524
151
 
1525
152
  callable_info = (GICallableInfo *)info;
1526
- arguments_init(&in_args, &out_args, &args_metadata);
1527
- if (receiver.v_pointer) {
1528
- g_array_append_val(in_args, receiver);
1529
- }
1530
- arguments_from_ruby(callable_info, rb_receiver, rb_arguments,
1531
- in_args, out_args, args_metadata);
153
+ rb_gi_arguments_init(&args,
154
+ callable_info,
155
+ rb_receiver,
156
+ rb_arguments,
157
+ NULL);
1532
158
  {
1533
159
  InvokeData data;
1534
160
  data.info = info;
1535
- data.in_args = in_args;
1536
- data.out_args = out_args;
161
+ data.in_args = args.in_args;
162
+ data.out_args = args.out_args;
1537
163
  data.error = &error;
1538
164
  if (unlock_gvl) {
1539
165
  rb_thread_call_without_gvl(
@@ -1544,20 +170,14 @@ rb_gi_function_info_invoke_raw(GIFunctionInfo *info,
1544
170
  }
1545
171
  succeeded = data.succeeded;
1546
172
 
1547
- if (rb_receiver_is_class) {
1548
- g_type_class_unref(receiver.v_pointer);
1549
- }
1550
-
1551
173
  if (return_value) {
1552
174
  *return_value = data.return_value;
1553
175
  }
1554
176
  if (rb_return_value) {
1555
177
  if (succeeded) {
1556
- *rb_return_value = GI_RETURN_ARGUMENT2RVAL(callable_info,
1557
- &(data.return_value),
1558
- in_args,
1559
- out_args,
1560
- args_metadata);
178
+ *rb_return_value =
179
+ rb_gi_arguments_get_rb_return_value(&args,
180
+ &(data.return_value));
1561
181
  } else {
1562
182
  *rb_return_value = Qnil;
1563
183
  }
@@ -1565,18 +185,16 @@ rb_gi_function_info_invoke_raw(GIFunctionInfo *info,
1565
185
  }
1566
186
 
1567
187
  if (succeeded) {
1568
- rb_out_args = out_arguments_to_ruby(callable_info,
1569
- in_args, out_args,
1570
- args_metadata);
188
+ rb_out_args = rb_gi_arguments_get_rb_out_args(&args);
1571
189
  }
1572
- arguments_free(rb_arguments, in_args, out_args, args_metadata);
190
+ rb_gi_arguments_clear(&args);
1573
191
  if (!succeeded) {
1574
192
  RG_RAISE_ERROR(error);
1575
193
  }
1576
194
 
1577
195
  if (!NIL_P(rb_out_args) && RARRAY_LEN(rb_out_args) == 1) {
1578
196
  VALUE rb_out_arg;
1579
- rb_out_arg = RARRAY_PTR(rb_out_args)[0];
197
+ rb_out_arg = RARRAY_AREF(rb_out_args, 0);
1580
198
  if (rb_obj_is_kind_of(rb_out_arg, rb_eException)) {
1581
199
  rb_exc_raise(rb_out_arg);
1582
200
  }
@@ -1621,17 +239,10 @@ rg_invoke(VALUE self, VALUE rb_arguments)
1621
239
  void
1622
240
  rb_gi_function_info_init(VALUE rb_mGI, VALUE rb_cGICallableInfo)
1623
241
  {
1624
- rb_cGLibError = rb_const_get(mGLib, rb_intern("Error"));
1625
-
1626
242
  RG_TARGET_NAMESPACE =
1627
243
  G_DEF_CLASS_WITH_PARENT(GI_TYPE_FUNCTION_INFO, "FunctionInfo", rb_mGI,
1628
244
  rb_cGICallableInfo);
1629
245
 
1630
- rb_iv_set(RG_TARGET_NAMESPACE, callbacks_key, rb_hash_new());
1631
-
1632
- callback_finders = g_ptr_array_new();
1633
- rb_gi_callback_register_finder(source_func_callback_finder);
1634
-
1635
246
  RG_DEF_METHOD(set_unlock_gvl, 1);
1636
247
  RG_DEF_METHOD_P(unlock_gvl, 0);
1637
248