gobject-introspection 1.1.9 → 1.2.0

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.
@@ -72,7 +72,7 @@ rg_n_args(VALUE self)
72
72
  }
73
73
 
74
74
  static VALUE
75
- rg_operator_aref(VALUE self, VALUE rb_n)
75
+ rg_get_arg(VALUE self, VALUE rb_n)
76
76
  {
77
77
  GICallableInfo *info;
78
78
  gint n;
@@ -82,25 +82,6 @@ rg_operator_aref(VALUE self, VALUE rb_n)
82
82
  return GI_BASE_INFO2RVAL_WITH_UNREF(g_callable_info_get_arg(info, n));
83
83
  }
84
84
 
85
- static VALUE
86
- rg_args(VALUE self)
87
- {
88
- GICallableInfo *info;
89
- gint i, n;
90
- VALUE rb_args;
91
-
92
- info = SELF(self);
93
- rb_args = rb_ary_new();
94
- n = g_callable_info_get_n_args(info);
95
- for (i = 0; i < n; i++) {
96
- GIArgInfo *arg_info;
97
- arg_info = g_callable_info_get_arg(info, i);
98
- rb_ary_push(rb_args, GI_BASE_INFO2RVAL_WITH_UNREF(arg_info));
99
- }
100
-
101
- return rb_args;
102
- }
103
-
104
85
  void
105
86
  rb_gi_callable_info_init(VALUE rb_mGI, VALUE rb_cGIBaseInfo)
106
87
  {
@@ -114,8 +95,7 @@ rb_gi_callable_info_init(VALUE rb_mGI, VALUE rb_cGIBaseInfo)
114
95
  RG_DEF_METHOD(caller_owns, 0);
115
96
  RG_DEF_METHOD_P(may_return_null, 0);
116
97
  RG_DEF_METHOD(n_args, 0);
117
- RG_DEF_METHOD_OPERATOR("[]", aref, 1);
118
- RG_DEF_METHOD(args, 0);
98
+ RG_DEF_METHOD(get_arg, 1);
119
99
 
120
100
  rb_gi_function_info_init(rb_mGI, RG_TARGET_NAMESPACE);
121
101
  rb_gi_callback_info_init(rb_mGI, RG_TARGET_NAMESPACE);
@@ -35,6 +35,52 @@ gi_constructor_info_get_type(void)
35
35
  return type;
36
36
  }
37
37
 
38
+ static void
39
+ initialize_receiver(VALUE receiver, GITypeInfo *info, GIArgument *value)
40
+ {
41
+ GIBaseInfo *interface_info;
42
+ GIInfoType interface_type;
43
+
44
+ if (g_type_info_get_tag(info) != GI_TYPE_TAG_INTERFACE) {
45
+ rb_raise(rb_eRuntimeError, "TODO: returned value isn't interface");
46
+ }
47
+
48
+ interface_info = g_type_info_get_interface(info);
49
+ interface_type = g_base_info_get_type(interface_info);
50
+ g_base_info_unref(interface_info);
51
+ switch (interface_type) {
52
+ case GI_INFO_TYPE_OBJECT:
53
+ g_object_ref_sink(value->v_pointer);
54
+ G_INITIALIZE(receiver, value->v_pointer);
55
+ break;
56
+ case GI_INFO_TYPE_STRUCT:
57
+ G_INITIALIZE(receiver, value->v_pointer);
58
+ break;
59
+ case GI_INFO_TYPE_INVALID:
60
+ case GI_INFO_TYPE_FUNCTION:
61
+ case GI_INFO_TYPE_CALLBACK:
62
+ case GI_INFO_TYPE_BOXED:
63
+ case GI_INFO_TYPE_ENUM:
64
+ case GI_INFO_TYPE_FLAGS:
65
+ case GI_INFO_TYPE_INTERFACE:
66
+ case GI_INFO_TYPE_CONSTANT:
67
+ case GI_INFO_TYPE_INVALID_0:
68
+ case GI_INFO_TYPE_UNION:
69
+ case GI_INFO_TYPE_VALUE:
70
+ case GI_INFO_TYPE_SIGNAL:
71
+ case GI_INFO_TYPE_VFUNC:
72
+ case GI_INFO_TYPE_PROPERTY:
73
+ case GI_INFO_TYPE_FIELD:
74
+ case GI_INFO_TYPE_ARG:
75
+ case GI_INFO_TYPE_TYPE:
76
+ case GI_INFO_TYPE_UNRESOLVED:
77
+ default:
78
+ rb_raise(rb_eRuntimeError,
79
+ "TODO: returned value isn't object or struct");
80
+ break;
81
+ }
82
+ }
83
+
38
84
  static VALUE
39
85
  rg_invoke(int argc, VALUE *argv, VALUE self)
40
86
  {
@@ -43,27 +89,19 @@ rg_invoke(int argc, VALUE *argv, VALUE self)
43
89
  VALUE receiver;
44
90
  GIArgument return_value;
45
91
  GITypeInfo return_value_info;
46
- GIBaseInfo *interface_info;
47
- GIInfoType interface_type;
48
92
 
49
93
  info = SELF(self);
50
94
  callable_info = (GICallableInfo *)info;
51
95
 
52
96
  /* TODO: check argc. */
53
97
  receiver = argv[0];
54
- rb_gi_function_info_invoke_raw(info, argc - 1, argv + 1, &return_value);
55
- g_callable_info_load_return_type(callable_info, &return_value_info);
98
+ /* TODO: use rb_protect */
99
+ rb_gi_function_info_invoke_raw(info, NULL,
100
+ argc - 1, argv + 1,
101
+ &return_value);
56
102
 
57
- if (g_type_info_get_tag(&return_value_info) != GI_TYPE_TAG_INTERFACE) {
58
- rb_raise(rb_eRuntimeError, "TODO: returned value isn't interface");
59
- }
60
- interface_info = g_type_info_get_interface(&return_value_info);
61
- interface_type = g_base_info_get_type(interface_info);
62
- if (interface_type != GI_INFO_TYPE_OBJECT) {
63
- rb_raise(rb_eRuntimeError, "TODO: returned value isn't object");
64
- }
65
- g_object_ref_sink(return_value.v_pointer);
66
- G_INITIALIZE(receiver, return_value.v_pointer);
103
+ g_callable_info_load_return_type(callable_info, &return_value_info);
104
+ initialize_receiver(receiver, &return_value_info, &return_value);
67
105
 
68
106
  return receiver;
69
107
  }
@@ -1,6 +1,6 @@
1
1
  /* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
2
2
  /*
3
- * Copyright (C) 2012 Ruby-GNOME2 Project Team
3
+ * Copyright (C) 2012-2013 Ruby-GNOME2 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
@@ -33,8 +33,14 @@
33
33
 
34
34
  #define GI_ARGUMENT2RVAL(argument, type_info) \
35
35
  (rb_gi_argument_to_ruby((argument), (type_info)))
36
- #define RVAL2GI_ARGUMENT(argument, type_info, rb_argument) \
37
- (rb_gi_argument_from_ruby((argument), (type_info), (rb_argument)))
36
+ #define GI_OUT_ARGUMENT2RVAL(argument, arg_info) \
37
+ (rb_gi_out_argument_to_ruby((argument), (arg_info)))
38
+ #define GI_RETURN_ARGUMENT2RVAL(argument, callable_info) \
39
+ (rb_gi_return_argument_to_ruby((argument), (callable_info)))
40
+ #define RVAL2GI_IN_ARGUMENT(argument, type_info, rb_argument) \
41
+ (rb_gi_in_argument_from_ruby((argument), (type_info), (rb_argument)))
42
+ #define RVAL2GI_CALL_ARGUMENT(argument, arg_info, rb_argument) \
43
+ (rb_gi_call_argument_from_ruby((argument), (arg_info), (rb_argument)))
38
44
 
39
45
 
40
46
  #define RVAL2GI_REGISTERED_TYPE_INFO(rb_object) \
@@ -83,11 +89,26 @@ VALUE rb_gi_base_info_to_ruby (GIBaseInfo *info);
83
89
  VALUE rb_gi_base_info_to_ruby_with_unref(GIBaseInfo *info);
84
90
  GIBaseInfo *rb_gi_base_info_from_ruby (VALUE rb_info);
85
91
 
86
- VALUE rb_gi_argument_to_ruby (GIArgument *argument,
87
- GITypeInfo *type_info);
88
- GIArgument *rb_gi_argument_from_ruby (GIArgument *argument,
89
- GITypeInfo *type_info,
90
- VALUE rb_argument);
92
+ VALUE rb_gi_argument_to_ruby (GIArgument *argument,
93
+ GITypeInfo *type_info);
94
+ void rb_gi_out_argument_init (GIArgument *argument,
95
+ GIArgInfo *arg_info);
96
+ VALUE rb_gi_out_argument_to_ruby (GIArgument *argument,
97
+ GIArgInfo *arg_info);
98
+ void rb_gi_out_argument_fin (GIArgument *argument,
99
+ GIArgInfo *arg_info);
100
+ VALUE rb_gi_return_argument_to_ruby (GIArgument *argument,
101
+ GICallableInfo *callable_info);
102
+ GIArgument *rb_gi_in_argument_from_ruby (GIArgument *argument,
103
+ GITypeInfo *type_info,
104
+ VALUE rb_argument);
105
+ GIArgument *rb_gi_call_argument_from_ruby (GIArgument *argument,
106
+ GIArgInfo *arg_info,
107
+ VALUE rb_argument);
108
+ void rb_gi_in_argument_free (GIArgument *argument,
109
+ GITypeInfo *type_info);
110
+ void rb_gi_call_argument_free (GIArgument *argument,
111
+ GIArgInfo *arg_info);
91
112
 
92
113
  VALUE rb_gi_array_type_to_ruby (GIArrayType type);
93
114
 
@@ -1,6 +1,6 @@
1
1
  /* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
2
2
  /*
3
- * Copyright (C) 2012 Ruby-GNOME2 Project Team
3
+ * Copyright (C) 2012-2013 Ruby-GNOME2 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
@@ -95,12 +95,16 @@ rb_gi_field_info_set_field_raw(GIFieldInfo *info, gpointer memory,
95
95
  {
96
96
  GIArgument field_value;
97
97
  GITypeInfo *type_info;
98
+ gboolean succeeded;
98
99
 
99
100
  type_info = g_field_info_get_type(info);
100
- RVAL2GI_ARGUMENT(&field_value, type_info, rb_field_value);
101
+ RVAL2GI_IN_ARGUMENT(&field_value, type_info, rb_field_value);
102
+
103
+ succeeded = g_field_info_set_field(info, memory, &field_value);
104
+ rb_gi_in_argument_free(&field_value, type_info);
101
105
  g_base_info_unref(type_info);
102
106
 
103
- if (!g_field_info_set_field(info, memory, &field_value)) {
107
+ if (!succeeded) {
104
108
  rb_raise(rb_eArgError, "failed to set field value");
105
109
  }
106
110
  }
@@ -1,6 +1,6 @@
1
1
  /* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
2
2
  /*
3
- * Copyright (C) 2012 Ruby-GNOME2 Project Team
3
+ * Copyright (C) 2012-2013 Ruby-GNOME2 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
@@ -23,6 +23,9 @@
23
23
  #define RG_TARGET_NAMESPACE rb_cGIFunctionInfo
24
24
  #define SELF(self) RVAL2GI_FUNCTION_INFO(self)
25
25
 
26
+ static VALUE RG_TARGET_NAMESPACE;
27
+ static const char *callbacks_key = "gi_callbacks";
28
+
26
29
  GType
27
30
  gi_function_info_get_type(void)
28
31
  {
@@ -71,81 +74,478 @@ rg_vfunc(VALUE self)
71
74
  return GI_BASE_INFO2RVAL(g_function_info_get_vfunc(info));
72
75
  }
73
76
 
77
+ typedef struct
78
+ {
79
+ GIArgInfo arg_info;
80
+ GIScopeType scope_type;
81
+ GIDirection direction;
82
+ gboolean callback_p;
83
+ gboolean closure_p;
84
+ gboolean destroy_p;
85
+ gboolean inout_argv_p;
86
+ gint in_arg_index;
87
+ gint closure_in_arg_index;
88
+ gint destroy_in_arg_index;
89
+ gint rb_arg_index;
90
+ gint out_arg_index;
91
+ gint inout_argc_arg_index;
92
+ } ArgMetadata;
93
+
74
94
  static void
75
- fill_gi_argument_by_ruby(GIArgument *argument, GIArgInfo *arg_info,
76
- VALUE rb_argument)
95
+ allocate_arguments(GICallableInfo *info,
96
+ GArray *in_args, GArray *out_args,
97
+ GPtrArray *args_metadata)
98
+ {
99
+ gint i, n_args;
100
+ gint rb_arg_index = 0;
101
+
102
+ n_args = g_callable_info_get_n_args(info);
103
+ for (i = 0; i < n_args; i++) {
104
+ GIArgument argument;
105
+ ArgMetadata *metadata;
106
+ GIArgInfo *arg_info;
107
+ GIDirection direction;
108
+
109
+ memset(&argument, 0, sizeof(GIArgument));
110
+
111
+ metadata = ALLOC(ArgMetadata);
112
+ arg_info = &(metadata->arg_info);
113
+ g_callable_info_load_arg(info, i, arg_info);
114
+ metadata->scope_type = g_arg_info_get_scope(arg_info);
115
+ metadata->direction = g_arg_info_get_direction(arg_info);
116
+ metadata->callback_p = (metadata->scope_type != GI_SCOPE_TYPE_INVALID);
117
+ metadata->closure_p = FALSE;
118
+ metadata->destroy_p = FALSE;
119
+ metadata->inout_argv_p = FALSE;
120
+ metadata->in_arg_index = -1;
121
+ metadata->closure_in_arg_index = -1;
122
+ metadata->destroy_in_arg_index = -1;
123
+ metadata->rb_arg_index = -1;
124
+ metadata->out_arg_index = -1;
125
+ metadata->inout_argc_arg_index = -1;
126
+
127
+ direction = metadata->direction;
128
+ if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) {
129
+ metadata->in_arg_index = in_args->len;
130
+ g_array_append_val(in_args, argument);
131
+ metadata->rb_arg_index = rb_arg_index++;
132
+ }
133
+ if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) {
134
+ metadata->out_arg_index = out_args->len;
135
+ g_array_append_val(out_args, argument);
136
+ }
137
+
138
+ g_ptr_array_add(args_metadata, metadata);
139
+ }
140
+ }
141
+
142
+ static void
143
+ fill_metadata_inout_argv(GPtrArray *args_metadata)
144
+ {
145
+ guint i;
146
+ gint inout_argc_arg_index = -1;
147
+
148
+ for (i = 0; i < args_metadata->len; i++) {
149
+ ArgMetadata *metadata;
150
+ GIArgInfo *arg_info;
151
+ const gchar *name;
152
+
153
+ metadata = g_ptr_array_index(args_metadata, i);
154
+ if (metadata->direction != GI_DIRECTION_INOUT) {
155
+ continue;
156
+ }
157
+ arg_info = &(metadata->arg_info);
158
+ name = g_base_info_get_name(arg_info);
159
+ if (strcmp(name, "argc") == 0) {
160
+ inout_argc_arg_index = i;
161
+ } else if (strcmp(name, "argv") == 0) {
162
+ metadata->inout_argv_p = TRUE;
163
+ metadata->inout_argc_arg_index = inout_argc_arg_index;
164
+ }
165
+ }
166
+ }
167
+
168
+ static void
169
+ fill_metadata_callback(GPtrArray *args_metadata)
170
+ {
171
+ guint i;
172
+
173
+ for (i = 0; i < args_metadata->len; i++) {
174
+ ArgMetadata *metadata;
175
+ GIArgInfo *arg_info;
176
+ gint closure_index;
177
+ gint destroy_index;
178
+
179
+ metadata = g_ptr_array_index(args_metadata, i);
180
+ if (!metadata->callback_p) {
181
+ continue;
182
+ }
183
+
184
+ arg_info = &(metadata->arg_info);
185
+ closure_index = g_arg_info_get_closure(arg_info);
186
+ if (closure_index != -1) {
187
+ ArgMetadata *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
+ closure_metadata->rb_arg_index = -1;
192
+ }
193
+
194
+ destroy_index = g_arg_info_get_destroy(arg_info);
195
+ if (destroy_index != -1) {
196
+ ArgMetadata *destroy_metadata;
197
+ destroy_metadata = g_ptr_array_index(args_metadata, destroy_index);
198
+ destroy_metadata->destroy_p = TRUE;
199
+ metadata->destroy_in_arg_index = destroy_metadata->in_arg_index;
200
+ destroy_metadata->rb_arg_index = -1;
201
+ }
202
+ }
203
+ }
204
+
205
+ static void
206
+ fill_metadata(GPtrArray *args_metadata)
207
+ {
208
+ fill_metadata_inout_argv(args_metadata);
209
+ fill_metadata_callback(args_metadata);
210
+ }
211
+
212
+ static gboolean
213
+ source_callback_p(GIArgInfo *info)
77
214
  {
78
215
  GITypeInfo type_info;
216
+ GIBaseInfo *interface_info;
217
+ GICallableInfo *callback_info;
218
+ GITypeInfo return_type_info;
219
+ GIArgInfo first_arg_info;
220
+ GITypeInfo first_arg_type_info;
221
+
222
+ g_arg_info_load_type(info, &type_info);
223
+ if (g_type_info_get_tag(&type_info) != GI_TYPE_TAG_INTERFACE) {
224
+ return FALSE;
225
+ }
79
226
 
80
- g_arg_info_load_type(arg_info, &type_info);
81
- RVAL2GI_ARGUMENT(argument, &type_info, rb_argument);
227
+ interface_info = g_type_info_get_interface(&type_info);
228
+ if (g_base_info_get_type(interface_info) != GI_INFO_TYPE_CALLBACK) {
229
+ g_base_info_unref(interface_info);
230
+ return FALSE;
231
+ }
232
+
233
+ callback_info = (GICallableInfo *)interface_info;
234
+ g_callable_info_load_return_type(callback_info, &return_type_info);
235
+ if (g_type_info_get_tag(&return_type_info) != GI_TYPE_TAG_BOOLEAN) {
236
+ g_base_info_unref(interface_info);
237
+ return FALSE;
238
+ }
239
+
240
+ if (g_callable_info_get_n_args(interface_info) != 1) {
241
+ g_base_info_unref(interface_info);
242
+ return FALSE;
243
+ }
244
+
245
+ g_callable_info_load_arg(interface_info, 0, &first_arg_info);
246
+ g_arg_info_load_type(&first_arg_info, &first_arg_type_info);
247
+ if (g_type_info_get_tag(&first_arg_type_info) != GI_TYPE_TAG_VOID) {
248
+ g_base_info_unref(interface_info);
249
+ return FALSE;
250
+ }
251
+
252
+ g_base_info_unref(interface_info);
253
+ return TRUE;
82
254
  }
83
255
 
256
+ typedef struct {
257
+ ArgMetadata *metadata;
258
+ VALUE rb_gc_guard_key;
259
+ VALUE rb_callback;
260
+ } CallbackData;
261
+
84
262
  static void
85
- fill_in_argument(GIArgInfo *arg_info, GArray *in_args, int argc, VALUE *argv)
263
+ callback_data_guard_from_gc(CallbackData *callback_data)
86
264
  {
87
- VALUE rb_argument;
88
- GIArgument argument;
265
+ VALUE rb_callbacks;
89
266
 
90
- /* TODO: check argc */
91
- rb_argument = argv[in_args->len];
92
- fill_gi_argument_by_ruby(&argument, arg_info, rb_argument);
93
- g_array_append_val(in_args, argument);
267
+ rb_callbacks = rb_iv_get(RG_TARGET_NAMESPACE, callbacks_key);
268
+ callback_data->rb_gc_guard_key = rb_class_new_instance(0, NULL, rb_cObject);
269
+ rb_hash_aset(rb_callbacks,
270
+ callback_data->rb_gc_guard_key,
271
+ callback_data->rb_callback);
94
272
  }
95
273
 
96
274
  static void
97
- fill_out_argument(G_GNUC_UNUSED GIArgInfo *arg_info, GArray *out_args)
275
+ callback_data_unguard_from_gc(CallbackData *callback_data)
98
276
  {
99
- GIArgument argument;
100
- g_array_append_val(out_args, argument);
277
+ VALUE rb_callbacks;
278
+
279
+ rb_callbacks = rb_iv_get(RG_TARGET_NAMESPACE, callbacks_key);
280
+ rb_hash_delete(rb_callbacks, callback_data->rb_gc_guard_key);
101
281
  }
102
282
 
103
283
  static void
104
- fill_argument(GIArgInfo *arg_info, GArray *in_args, GArray *out_args,
105
- int argc, VALUE *argv)
106
- {
107
- switch (g_arg_info_get_direction(arg_info)) {
108
- case GI_DIRECTION_IN:
109
- fill_in_argument(arg_info, in_args, argc, argv);
110
- break;
111
- case GI_DIRECTION_OUT:
112
- fill_out_argument(arg_info, out_args);
113
- break;
114
- case GI_DIRECTION_INOUT:
115
- fill_in_argument(arg_info, in_args, argc, argv);
116
- fill_out_argument(arg_info, out_args);
117
- break;
118
- default:
119
- g_assert_not_reached();
120
- break;
284
+ callback_data_free(CallbackData *callback_data)
285
+ {
286
+ callback_data_unguard_from_gc(callback_data);
287
+ xfree(callback_data->metadata);
288
+ xfree(callback_data);
289
+ }
290
+
291
+ static gboolean
292
+ source_callback(gpointer user_data)
293
+ {
294
+ CallbackData *callback_data = user_data;
295
+ VALUE rb_keep;
296
+ ID id_call;
297
+
298
+ CONST_ID(id_call, "call");
299
+ rb_keep = rb_funcall(callback_data->rb_callback, id_call, 0);
300
+ if (callback_data->metadata->scope_type == GI_SCOPE_TYPE_ASYNC) {
301
+ callback_data_free(callback_data);
121
302
  }
303
+ return RVAL2CBOOL(rb_keep);
122
304
  }
123
305
 
124
- void
125
- rb_gi_function_info_invoke_raw(GIFunctionInfo *info, int argc, VALUE *argv,
306
+ static void
307
+ destroy_notify(gpointer data)
308
+ {
309
+ CallbackData *callback_data = data;
310
+ callback_data_free(callback_data);
311
+ }
312
+
313
+ static void
314
+ in_callback_argument_from_ruby(ArgMetadata *metadata, VALUE *argv,
315
+ GArray *in_args)
316
+ {
317
+ GIArgument *callback_argument;
318
+
319
+ if (!source_callback_p(&(metadata->arg_info))) {
320
+ rb_raise(rb_eNotImpError,
321
+ "TODO: GSourceFunc callback is only supported.");
322
+ }
323
+
324
+ callback_argument = &(g_array_index(in_args,
325
+ GIArgument,
326
+ metadata->in_arg_index));
327
+ callback_argument->v_pointer = source_callback;
328
+
329
+ if (metadata->closure_in_arg_index != -1) {
330
+ CallbackData *callback_data;
331
+ GIArgument *closure_argument;
332
+
333
+ callback_data = ALLOC(CallbackData);
334
+ callback_data->metadata = metadata;
335
+ callback_data->rb_callback = rb_block_proc();
336
+ callback_data_guard_from_gc(callback_data);
337
+ closure_argument = &(g_array_index(in_args,
338
+ GIArgument,
339
+ metadata->closure_in_arg_index));
340
+ closure_argument->v_pointer = callback_data;
341
+ }
342
+
343
+ if (metadata->destroy_in_arg_index != -1) {
344
+ GIArgument *destroy_argument;
345
+ destroy_argument = &(g_array_index(in_args,
346
+ GIArgument,
347
+ metadata->destroy_in_arg_index));
348
+ destroy_argument->v_pointer = destroy_notify;
349
+ }
350
+ }
351
+
352
+ static void
353
+ in_argument_from_ruby(ArgMetadata *metadata, VALUE *argv, GArray *in_args)
354
+ {
355
+ if (metadata->rb_arg_index == -1) {
356
+ return;
357
+ }
358
+
359
+ if (metadata->callback_p) {
360
+ in_callback_argument_from_ruby(metadata, argv, in_args);
361
+ } else {
362
+ GIArgument *argument;
363
+
364
+ argument = &(g_array_index(in_args, GIArgument, metadata->in_arg_index));
365
+ RVAL2GI_CALL_ARGUMENT(argument,
366
+ &(metadata->arg_info),
367
+ argv[metadata->rb_arg_index]);
368
+ }
369
+ }
370
+
371
+ static void
372
+ out_argument_from_ruby(ArgMetadata *metadata, GArray *out_args)
373
+ {
374
+ GIArgument *argument;
375
+
376
+ argument = &(g_array_index(out_args, GIArgument, metadata->out_arg_index));
377
+ rb_gi_out_argument_init(argument, &(metadata->arg_info));
378
+ }
379
+
380
+ static void
381
+ arg_metadata_free(gpointer data)
382
+ {
383
+ ArgMetadata *metadata = data;
384
+ if (metadata->scope_type == GI_SCOPE_TYPE_ASYNC ||
385
+ metadata->scope_type == GI_SCOPE_TYPE_NOTIFIED) {
386
+ return;
387
+ }
388
+ xfree(metadata);
389
+ }
390
+
391
+ static void
392
+ arguments_from_ruby(GICallableInfo *info,
393
+ int argc, VALUE *argv,
394
+ GArray *in_args, GArray *out_args,
395
+ GPtrArray *args_metadata)
396
+ {
397
+ gint i, n_args;
398
+
399
+ allocate_arguments(info, in_args, out_args, args_metadata);
400
+ fill_metadata(args_metadata);
401
+
402
+ /* TODO: validate_rb_args(args_metadata); */
403
+
404
+ n_args = g_callable_info_get_n_args(info);
405
+ for (i = 0; i < n_args; i++) {
406
+ ArgMetadata *metadata;
407
+
408
+ metadata = g_ptr_array_index(args_metadata, i);
409
+ if (metadata->in_arg_index != -1) {
410
+ in_argument_from_ruby(metadata, argv, in_args);
411
+ } else {
412
+ out_argument_from_ruby(metadata, out_args);
413
+ }
414
+ }
415
+ }
416
+
417
+ static VALUE
418
+ inout_argv_argument_to_ruby(GArray *in_args, ArgMetadata *metadata)
419
+ {
420
+ GIArgument *inout_argc_argument;
421
+ GIArgument *inout_argv_argument;
422
+ gint i, argc;
423
+ gchar **argv;
424
+ VALUE rb_argv_argument;
425
+
426
+ inout_argc_argument = &g_array_index(in_args, GIArgument,
427
+ metadata->inout_argc_arg_index);
428
+ inout_argv_argument = &g_array_index(in_args, GIArgument,
429
+ metadata->in_arg_index);
430
+ argc = *((gint *)(inout_argc_argument->v_pointer));
431
+ argv = *((gchar ***)(inout_argv_argument->v_pointer));
432
+ rb_argv_argument = rb_ary_new2(argc);
433
+ for (i = 0; i < argc; i++) {
434
+ rb_ary_push(rb_argv_argument, CSTR2RVAL(argv[i]));
435
+ }
436
+ return rb_argv_argument;
437
+ }
438
+
439
+ static VALUE
440
+ out_arguments_to_ruby(GICallableInfo *callable_info,
441
+ GArray *in_args, GArray *out_args,
442
+ GPtrArray *args_metadata)
443
+ {
444
+ gint i, n_args;
445
+ VALUE rb_out_args;
446
+
447
+ rb_out_args = rb_ary_new();
448
+ n_args = g_callable_info_get_n_args(callable_info);
449
+ for (i = 0; i < n_args; i++) {
450
+ ArgMetadata *metadata;
451
+ GIArgument *argument = NULL;
452
+ VALUE rb_argument;
453
+
454
+ metadata = g_ptr_array_index(args_metadata, i);
455
+ switch (metadata->direction) {
456
+ case GI_DIRECTION_IN:
457
+ break;
458
+ case GI_DIRECTION_OUT:
459
+ argument = &g_array_index(out_args, GIArgument,
460
+ metadata->out_arg_index);
461
+ break;
462
+ case GI_DIRECTION_INOUT:
463
+ argument = &g_array_index(in_args, GIArgument,
464
+ metadata->in_arg_index);
465
+ break;
466
+ default:
467
+ g_assert_not_reached();
468
+ break;
469
+ }
470
+
471
+ if (!argument) {
472
+ continue;
473
+ }
474
+
475
+ if (metadata->inout_argv_p) {
476
+ rb_argument = inout_argv_argument_to_ruby(in_args, metadata);
477
+ } else {
478
+ rb_argument = GI_OUT_ARGUMENT2RVAL(argument, &(metadata->arg_info));
479
+ }
480
+ rb_ary_push(rb_out_args, rb_argument);
481
+ }
482
+
483
+ if (RARRAY_LEN(rb_out_args) == 0) {
484
+ return Qnil;
485
+ } else {
486
+ return rb_out_args;
487
+ }
488
+ }
489
+
490
+ static void
491
+ arguments_init(GArray **in_args, GArray **out_args, GPtrArray **args_metadata)
492
+ {
493
+ *in_args = g_array_new(FALSE, FALSE, sizeof(GIArgument));
494
+ *out_args = g_array_new(FALSE, FALSE, sizeof(GIArgument));
495
+ *args_metadata = g_ptr_array_new_with_free_func(arg_metadata_free);
496
+ }
497
+
498
+ static void
499
+ arguments_free(GArray *in_args, GArray *out_args, GPtrArray *args_metadata)
500
+ {
501
+ guint i;
502
+
503
+ for (i = 0; i < args_metadata->len; i++) {
504
+ ArgMetadata *metadata;
505
+ gint in_arg_index;
506
+
507
+ metadata = g_ptr_array_index(args_metadata, i);
508
+ if (metadata->direction == GI_DIRECTION_IN ||
509
+ metadata->direction == GI_DIRECTION_INOUT) {
510
+ in_arg_index = metadata->in_arg_index;
511
+ if (in_arg_index != -1) {
512
+ GIArgument *argument;
513
+ argument = &(g_array_index(in_args, GIArgument, in_arg_index));
514
+ rb_gi_call_argument_free(argument, &(metadata->arg_info));
515
+ }
516
+ } else {
517
+ GIArgument *argument;
518
+ argument = &(g_array_index(out_args, GIArgument,
519
+ metadata->out_arg_index));
520
+ rb_gi_out_argument_fin(argument, &(metadata->arg_info));
521
+ }
522
+ }
523
+
524
+ g_array_unref(in_args);
525
+ g_array_unref(out_args);
526
+ g_ptr_array_unref(args_metadata);
527
+ }
528
+
529
+ VALUE
530
+ rb_gi_function_info_invoke_raw(GIFunctionInfo *info, GIArgument *receiver,
531
+ int argc, VALUE *argv,
126
532
  GIArgument *return_value)
127
533
  {
128
534
  GICallableInfo *callable_info;
129
- gint i, n_args;
130
535
  GArray *in_args, *out_args;
536
+ GPtrArray *args_metadata;
537
+ VALUE rb_out_args = Qnil;
131
538
  gboolean succeeded;
132
539
  GError *error = NULL;
133
540
 
134
541
  callable_info = (GICallableInfo *)info;
135
- n_args = g_callable_info_get_n_args(callable_info);
136
- in_args = g_array_new(FALSE, FALSE, sizeof(GIArgument));
137
- out_args = g_array_new(FALSE, FALSE, sizeof(GIArgument));
138
- if (g_function_info_get_flags(callable_info) & GI_FUNCTION_IS_METHOD) {
139
- GIArgument argument;
140
- /* TODO: check argc */
141
- argument.v_pointer = RVAL2GOBJ(argv[0]);
142
- g_array_append_val(in_args, argument);
143
- }
144
- for (i = 0; i < n_args; i++) {
145
- GIArgInfo arg_info;
146
- g_callable_info_load_arg(callable_info, i, &arg_info);
147
- fill_argument(&arg_info, in_args, out_args, argc, argv);
542
+ arguments_init(&in_args, &out_args, &args_metadata);
543
+ if (receiver) {
544
+ g_array_append_val(in_args, *receiver);
148
545
  }
546
+ arguments_from_ruby(callable_info,
547
+ argc, argv,
548
+ in_args, out_args, args_metadata);
149
549
  succeeded = g_function_info_invoke(info,
150
550
  (GIArgument *)(in_args->data),
151
551
  in_args->len,
@@ -153,11 +553,17 @@ rb_gi_function_info_invoke_raw(GIFunctionInfo *info, int argc, VALUE *argv,
153
553
  out_args->len,
154
554
  return_value,
155
555
  &error);
156
- g_array_unref(in_args);
157
- g_array_unref(out_args);
556
+ if (succeeded) {
557
+ rb_out_args = out_arguments_to_ruby(callable_info,
558
+ in_args, out_args,
559
+ args_metadata);
560
+ }
561
+ arguments_free(in_args, out_args, args_metadata);
158
562
  if (!succeeded) {
159
563
  RG_RAISE_ERROR(error);
160
564
  }
565
+
566
+ return rb_out_args;
161
567
  }
162
568
 
163
569
  static VALUE
@@ -166,26 +572,38 @@ rg_invoke(int argc, VALUE *argv, VALUE self)
166
572
  GIFunctionInfo *info;
167
573
  GICallableInfo *callable_info;
168
574
  GIArgument return_value;
169
- GITypeInfo return_value_info;
575
+ VALUE rb_out_args;
576
+ VALUE rb_return_value;
170
577
 
171
578
  info = SELF(self);
172
- callable_info = (GICallableInfo *)info;
579
+ /* TODO: use rb_protect() */
580
+ rb_out_args = rb_gi_function_info_invoke_raw(info, NULL, argc, argv,
581
+ &return_value);
173
582
 
174
- rb_gi_function_info_invoke_raw(info, argc, argv, &return_value);
175
- g_callable_info_load_return_type(callable_info, &return_value_info);
583
+ callable_info = (GICallableInfo *)info;
584
+ rb_return_value = GI_RETURN_ARGUMENT2RVAL(&return_value, callable_info);
176
585
 
177
- return GI_ARGUMENT2RVAL(&return_value, &return_value_info);
586
+ if (NIL_P(rb_out_args)) {
587
+ return rb_return_value;
588
+ } else {
589
+ GITypeInfo return_value_info;
590
+ g_callable_info_load_return_type(callable_info, &return_value_info);
591
+ if (g_type_info_get_tag(&return_value_info) != GI_TYPE_TAG_VOID) {
592
+ rb_ary_unshift(rb_out_args, rb_return_value);
593
+ }
594
+ return rb_out_args;
595
+ }
178
596
  }
179
597
 
180
598
  void
181
599
  rb_gi_function_info_init(VALUE rb_mGI, VALUE rb_cGICallableInfo)
182
600
  {
183
- VALUE RG_TARGET_NAMESPACE;
184
-
185
601
  RG_TARGET_NAMESPACE =
186
602
  G_DEF_CLASS_WITH_PARENT(GI_TYPE_FUNCTION_INFO, "FunctionInfo", rb_mGI,
187
603
  rb_cGICallableInfo);
188
604
 
605
+ rb_iv_set(RG_TARGET_NAMESPACE, callbacks_key, rb_hash_new());
606
+
189
607
  RG_DEF_METHOD(symbol, 0);
190
608
  RG_DEF_METHOD(flags, 0);
191
609
  RG_DEF_METHOD(property, 0);