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.
- data/Rakefile +2 -11
- data/ext/gobject-introspection/extconf.rb +3 -3
- data/ext/gobject-introspection/rb-gi-argument.c +836 -62
- data/ext/gobject-introspection/rb-gi-callable-info.c +2 -22
- data/ext/gobject-introspection/rb-gi-constructor-info.c +52 -14
- data/ext/gobject-introspection/rb-gi-conversions.h +29 -8
- data/ext/gobject-introspection/rb-gi-field-info.c +7 -3
- data/ext/gobject-introspection/rb-gi-function-info.c +475 -57
- data/ext/gobject-introspection/rb-gi-loader.c +94 -1
- data/ext/gobject-introspection/rb-gi-method-info.c +45 -6
- data/ext/gobject-introspection/rb-gi-struct-info.c +12 -5
- data/ext/gobject-introspection/rb-gi-union-info.c +1 -1
- data/ext/gobject-introspection/rb-gobject-introspection.c +3 -1
- data/ext/gobject-introspection/rb-gobject-introspection.h +4 -1
- data/lib/gobject-introspection.rb +4 -1
- data/lib/gobject-introspection/callable-info.rb +55 -0
- data/lib/gobject-introspection/interface-info.rb +32 -0
- data/lib/gobject-introspection/loader.rb +143 -34
- data/{sample/clutter.rb → lib/gobject-introspection/union-info.rb} +9 -10
- data/test/test-arg-info.rb +1 -1
- data/test/test-callable-info.rb +2 -2
- metadata +12 -11
- data/sample/clutter-basic-actor.rb +0 -132
@@ -72,7 +72,7 @@ rg_n_args(VALUE self)
|
|
72
72
|
}
|
73
73
|
|
74
74
|
static VALUE
|
75
|
-
|
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
|
-
|
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
|
-
|
55
|
-
|
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
|
-
|
58
|
-
|
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
|
37
|
-
(
|
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
|
87
|
-
GITypeInfo
|
88
|
-
|
89
|
-
|
90
|
-
|
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
|
-
|
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 (!
|
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
|
-
|
76
|
-
|
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
|
-
|
81
|
-
|
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
|
-
|
263
|
+
callback_data_guard_from_gc(CallbackData *callback_data)
|
86
264
|
{
|
87
|
-
VALUE
|
88
|
-
GIArgument argument;
|
265
|
+
VALUE rb_callbacks;
|
89
266
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
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
|
-
|
275
|
+
callback_data_unguard_from_gc(CallbackData *callback_data)
|
98
276
|
{
|
99
|
-
|
100
|
-
|
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
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
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
|
-
|
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
|
-
|
136
|
-
|
137
|
-
|
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
|
-
|
157
|
-
|
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
|
-
|
575
|
+
VALUE rb_out_args;
|
576
|
+
VALUE rb_return_value;
|
170
577
|
|
171
578
|
info = SELF(self);
|
172
|
-
|
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
|
-
|
175
|
-
|
583
|
+
callable_info = (GICallableInfo *)info;
|
584
|
+
rb_return_value = GI_RETURN_ARGUMENT2RVAL(&return_value, callable_info);
|
176
585
|
|
177
|
-
|
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);
|