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
@@ -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
|
@@ -22,6 +22,8 @@
|
|
22
22
|
|
23
23
|
#define RG_TARGET_NAMESPACE rb_cGILoader
|
24
24
|
|
25
|
+
static const gchar *boxed_class_converters_name = "@@boxed_class_converters";
|
26
|
+
|
25
27
|
static VALUE
|
26
28
|
rg_s_define_class(int argc, VALUE *argv, G_GNUC_UNUSED VALUE klass)
|
27
29
|
{
|
@@ -49,6 +51,93 @@ rg_s_define_interface(G_GNUC_UNUSED VALUE klass,
|
|
49
51
|
return G_DEF_INTERFACE(gtype, RVAL2CSTR(rb_name), rb_module);
|
50
52
|
}
|
51
53
|
|
54
|
+
static VALUE
|
55
|
+
struct_alloc(VALUE klass)
|
56
|
+
{
|
57
|
+
VALUE rb_size;
|
58
|
+
|
59
|
+
rb_size = rb_iv_get(klass, "@size");
|
60
|
+
return Data_Wrap_Struct(klass, NULL, xfree, xmalloc(NUM2ULONG(rb_size)));
|
61
|
+
}
|
62
|
+
|
63
|
+
static VALUE
|
64
|
+
rg_s_define_struct(int argc, VALUE *argv, G_GNUC_UNUSED VALUE klass)
|
65
|
+
{
|
66
|
+
VALUE rb_size, rb_name, rb_module;
|
67
|
+
VALUE rb_options, rb_parent;
|
68
|
+
VALUE rb_class;
|
69
|
+
|
70
|
+
rb_scan_args(argc, argv, "31", &rb_size, &rb_name, &rb_module, &rb_options);
|
71
|
+
rbg_scan_options(rb_options,
|
72
|
+
"parent", &rb_parent,
|
73
|
+
NULL);
|
74
|
+
|
75
|
+
rb_size = rb_to_int(rb_size);
|
76
|
+
if (NIL_P(rb_parent)) {
|
77
|
+
rb_parent = rb_cObject;
|
78
|
+
}
|
79
|
+
rb_class = rb_define_class_under(rb_module, RVAL2CSTR(rb_name), rb_parent);
|
80
|
+
rb_iv_set(rb_class, "@size", rb_size);
|
81
|
+
rb_define_alloc_func(rb_class, struct_alloc);
|
82
|
+
return rb_class;
|
83
|
+
}
|
84
|
+
|
85
|
+
typedef struct {
|
86
|
+
GType type;
|
87
|
+
VALUE rb_converters;
|
88
|
+
VALUE rb_converter;
|
89
|
+
} BoxedInstance2RObjData;
|
90
|
+
|
91
|
+
static void
|
92
|
+
boxed_class_converter_free(gpointer user_data)
|
93
|
+
{
|
94
|
+
BoxedInstance2RObjData *data = user_data;
|
95
|
+
rb_ary_delete(data->rb_converters, data->rb_converter);
|
96
|
+
g_free(data);
|
97
|
+
}
|
98
|
+
|
99
|
+
static VALUE
|
100
|
+
boxed_instance2robj(gpointer instance, gpointer user_data)
|
101
|
+
{
|
102
|
+
BoxedInstance2RObjData *data = user_data;
|
103
|
+
VALUE default_rb_instance;
|
104
|
+
VALUE klass;
|
105
|
+
gint flags = 0;
|
106
|
+
ID id_call;
|
107
|
+
|
108
|
+
default_rb_instance = rbgobj_make_boxed_default(instance, data->type);
|
109
|
+
CONST_ID(id_call, "call");
|
110
|
+
klass = rb_funcall(data->rb_converter, id_call, 1, default_rb_instance);
|
111
|
+
return rbgobj_make_boxed_raw(instance, data->type, klass, flags);
|
112
|
+
}
|
113
|
+
|
114
|
+
static VALUE
|
115
|
+
rg_s_register_boxed_class_converter(VALUE klass, VALUE rb_gtype)
|
116
|
+
{
|
117
|
+
RGConvertTable table;
|
118
|
+
BoxedInstance2RObjData *data;
|
119
|
+
ID id_to_i;
|
120
|
+
VALUE boxed_class_converters;
|
121
|
+
|
122
|
+
memset(&table, 0, sizeof(RGConvertTable));
|
123
|
+
CONST_ID(id_to_i, "to_i");
|
124
|
+
table.type = NUM2UINT(rb_funcall(rb_gtype, id_to_i, 0));
|
125
|
+
table.klass = Qnil;
|
126
|
+
table.instance2robj = boxed_instance2robj;
|
127
|
+
|
128
|
+
data = g_new(BoxedInstance2RObjData, 1);
|
129
|
+
data->type = table.type;
|
130
|
+
data->rb_converter = rb_block_proc();
|
131
|
+
boxed_class_converters = rb_cv_get(klass, boxed_class_converters_name);
|
132
|
+
rb_ary_push(boxed_class_converters, data->rb_converter);
|
133
|
+
table.user_data = data;
|
134
|
+
table.notify = boxed_class_converter_free;
|
135
|
+
|
136
|
+
rbgobj_convert_define(&table);
|
137
|
+
|
138
|
+
return Qnil;
|
139
|
+
}
|
140
|
+
|
52
141
|
void
|
53
142
|
rb_gi_loader_init(VALUE rb_mGI)
|
54
143
|
{
|
@@ -56,6 +145,10 @@ rb_gi_loader_init(VALUE rb_mGI)
|
|
56
145
|
|
57
146
|
RG_TARGET_NAMESPACE = rb_define_class_under(rb_mGI, "Loader", rb_cObject);
|
58
147
|
|
148
|
+
rb_cv_set(RG_TARGET_NAMESPACE, boxed_class_converters_name, rb_ary_new());
|
149
|
+
|
59
150
|
RG_DEF_SMETHOD(define_class, -1);
|
60
151
|
RG_DEF_SMETHOD(define_interface, 3);
|
152
|
+
RG_DEF_SMETHOD(define_struct, -1);
|
153
|
+
RG_DEF_SMETHOD(register_boxed_class_converter, 1);
|
61
154
|
}
|
@@ -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
|
@@ -35,22 +35,61 @@ gi_method_info_get_type(void)
|
|
35
35
|
return type;
|
36
36
|
}
|
37
37
|
|
38
|
+
static gboolean
|
39
|
+
gobject_based_p(GIFunctionInfo *info)
|
40
|
+
{
|
41
|
+
GIBaseInfo *container_info;
|
42
|
+
GIRegisteredTypeInfo *registered_type_info;
|
43
|
+
|
44
|
+
container_info = g_base_info_get_container((GIBaseInfo *)info);
|
45
|
+
if (g_base_info_get_type(container_info) != GI_INFO_TYPE_STRUCT) {
|
46
|
+
return TRUE;
|
47
|
+
}
|
48
|
+
|
49
|
+
registered_type_info = (GIRegisteredTypeInfo *)container_info;
|
50
|
+
if (g_registered_type_info_get_type_init(registered_type_info)) {
|
51
|
+
return TRUE;
|
52
|
+
}
|
53
|
+
|
54
|
+
return FALSE;
|
55
|
+
}
|
56
|
+
|
38
57
|
static VALUE
|
39
58
|
rg_invoke(int argc, VALUE *argv, VALUE self)
|
40
59
|
{
|
41
60
|
GIFunctionInfo *info;
|
42
61
|
GICallableInfo *callable_info;
|
62
|
+
GIArgument receiver;
|
43
63
|
GIArgument return_value;
|
44
|
-
|
64
|
+
VALUE rb_out_args;
|
65
|
+
VALUE rb_return_value;
|
45
66
|
|
46
67
|
info = SELF(self);
|
47
|
-
callable_info = (GICallableInfo *)info;
|
48
68
|
|
49
69
|
/* TODO: check argc >= 1 */
|
50
|
-
|
51
|
-
|
70
|
+
if (gobject_based_p(info)) {
|
71
|
+
receiver.v_pointer = RVAL2GOBJ(argv[0]);
|
72
|
+
} else {
|
73
|
+
receiver.v_pointer = DATA_PTR(argv[0]);
|
74
|
+
}
|
75
|
+
/* TODO: use rb_protect */
|
76
|
+
rb_out_args = rb_gi_function_info_invoke_raw(info, &receiver,
|
77
|
+
argc - 1, argv + 1,
|
78
|
+
&return_value);
|
52
79
|
|
53
|
-
|
80
|
+
callable_info = (GICallableInfo *)info;
|
81
|
+
rb_return_value = GI_RETURN_ARGUMENT2RVAL(&return_value, callable_info);
|
82
|
+
|
83
|
+
if (NIL_P(rb_out_args)) {
|
84
|
+
return rb_return_value;
|
85
|
+
} else {
|
86
|
+
GITypeInfo return_value_info;
|
87
|
+
g_callable_info_load_return_type(callable_info, &return_value_info);
|
88
|
+
if (g_type_info_get_tag(&return_value_info) != GI_TYPE_TAG_VOID) {
|
89
|
+
rb_ary_unshift(rb_out_args, rb_return_value);
|
90
|
+
}
|
91
|
+
return rb_out_args;
|
92
|
+
}
|
54
93
|
}
|
55
94
|
|
56
95
|
void
|
@@ -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
|
@@ -61,15 +61,22 @@ rg_get_field_value(VALUE self, VALUE rb_struct, VALUE rb_n)
|
|
61
61
|
GIStructInfo *info;
|
62
62
|
gint n;
|
63
63
|
GIFieldInfo *field_info;
|
64
|
-
GType gtype;
|
65
64
|
VALUE rb_value;
|
65
|
+
gpointer instance;
|
66
66
|
|
67
67
|
info = SELF(self);
|
68
68
|
n = NUM2INT(rb_n);
|
69
69
|
field_info = g_struct_info_get_field(info, n);
|
70
|
-
|
71
|
-
|
72
|
-
|
70
|
+
if (rb_respond_to(rb_struct, rb_intern("gtype"))) {
|
71
|
+
VALUE rb_gtype;
|
72
|
+
GType gtype;
|
73
|
+
rb_gtype = rb_funcall(rb_struct, rb_intern("gtype"), 0);
|
74
|
+
gtype = NUM2UINT(rb_funcall(rb_gtype, rb_intern("to_i"), 0));
|
75
|
+
instance = RVAL2BOXED(rb_struct, gtype);
|
76
|
+
} else {
|
77
|
+
Data_Get_Struct(rb_struct, void, instance);
|
78
|
+
}
|
79
|
+
rb_value = rb_gi_field_info_get_field_raw(field_info, instance);
|
73
80
|
g_base_info_unref(field_info);
|
74
81
|
|
75
82
|
return rb_value;
|
@@ -112,7 +112,7 @@ rg_get_method(VALUE self, VALUE rb_n_or_name)
|
|
112
112
|
GIFunctionInfo *function_info;
|
113
113
|
|
114
114
|
info = SELF(self);
|
115
|
-
if (RB_TYPE_P(
|
115
|
+
if (RB_TYPE_P(rb_n_or_name, T_FIXNUM)) {
|
116
116
|
gint n;
|
117
117
|
n = NUM2INT(rb_n_or_name);
|
118
118
|
function_info = g_union_info_get_method(info, n);
|
@@ -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
|
@@ -35,6 +35,8 @@ Init_gobject_introspection(void)
|
|
35
35
|
INT2FIX(GI_MINOR_VERSION),
|
36
36
|
INT2FIX(GI_MICRO_VERSION)));
|
37
37
|
|
38
|
+
rb_gi_argument_init();
|
39
|
+
|
38
40
|
rb_gi_type_tag_init(RG_TARGET_NAMESPACE);
|
39
41
|
rb_gi_base_info_init(RG_TARGET_NAMESPACE);
|
40
42
|
rb_gi_repository_init(RG_TARGET_NAMESPACE);
|
@@ -43,6 +43,8 @@
|
|
43
43
|
|
44
44
|
extern void Init_gobject_introspection(void);
|
45
45
|
|
46
|
+
void rb_gi_argument_init (void);
|
47
|
+
|
46
48
|
void rb_gi_type_tag_init (VALUE rb_mGI);
|
47
49
|
void rb_gi_base_info_init (VALUE rb_mGI);
|
48
50
|
void rb_gi_callable_info_init (VALUE rb_mGI,
|
@@ -92,7 +94,8 @@ void rb_gi_unresolved_info_init (VALUE rb_mGI,
|
|
92
94
|
void rb_gi_repository_init (VALUE rb_mGI);
|
93
95
|
void rb_gi_loader_init (VALUE rb_mGI);
|
94
96
|
|
95
|
-
|
97
|
+
VALUE rb_gi_function_info_invoke_raw (GIFunctionInfo *info,
|
98
|
+
GIArgument *receiver,
|
96
99
|
int argc, VALUE *argv,
|
97
100
|
GIArgument *return_value);
|
98
101
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (C) 2012 Ruby-GNOME2 Project Team
|
1
|
+
# Copyright (C) 2012-2013 Ruby-GNOME2 Project Team
|
2
2
|
#
|
3
3
|
# This library is free software; you can redistribute it and/or
|
4
4
|
# modify it under the terms of the GNU Lesser General Public
|
@@ -34,6 +34,9 @@ end
|
|
34
34
|
GLib::Log.set_log_domain(GObjectIntrospection::LOG_DOMAIN)
|
35
35
|
|
36
36
|
require "gobject-introspection/repository"
|
37
|
+
require "gobject-introspection/callable-info"
|
37
38
|
require "gobject-introspection/object-info"
|
39
|
+
require "gobject-introspection/interface-info"
|
38
40
|
require "gobject-introspection/struct-info"
|
41
|
+
require "gobject-introspection/union-info"
|
39
42
|
require "gobject-introspection/loader"
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# Copyright (C) 2013 Ruby-GNOME2 Project Team
|
2
|
+
#
|
3
|
+
# This library is free software; you can redistribute it and/or
|
4
|
+
# modify it under the terms of the GNU Lesser General Public
|
5
|
+
# License as published by the Free Software Foundation; either
|
6
|
+
# version 2.1 of the License, or (at your option) any later version.
|
7
|
+
#
|
8
|
+
# This library is distributed in the hope that it will be useful,
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
11
|
+
# Lesser General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU Lesser General Public
|
14
|
+
# License along with this library; if not, write to the Free Software
|
15
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
16
|
+
|
17
|
+
require "gobject-introspection/collection-reader"
|
18
|
+
|
19
|
+
module GObjectIntrospection
|
20
|
+
class CallableInfo
|
21
|
+
extend CollectionReader
|
22
|
+
|
23
|
+
collection_reader("args")
|
24
|
+
|
25
|
+
def in_args
|
26
|
+
args.find_all do |arg|
|
27
|
+
case arg.direction
|
28
|
+
when Direction::IN, Direction::INOUT
|
29
|
+
true
|
30
|
+
else
|
31
|
+
false
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def n_in_args
|
37
|
+
in_args.size
|
38
|
+
end
|
39
|
+
|
40
|
+
def out_args
|
41
|
+
args.find_all do |arg|
|
42
|
+
case arg.direction
|
43
|
+
when Direction::OUT, Direction::INOUT
|
44
|
+
true
|
45
|
+
else
|
46
|
+
false
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def n_out_args
|
52
|
+
out_args.size
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# Copyright (C) 2013 Ruby-GNOME2 Project Team
|
2
|
+
#
|
3
|
+
# This library is free software; you can redistribute it and/or
|
4
|
+
# modify it under the terms of the GNU Lesser General Public
|
5
|
+
# License as published by the Free Software Foundation; either
|
6
|
+
# version 2.1 of the License, or (at your option) any later version.
|
7
|
+
#
|
8
|
+
# This library is distributed in the hope that it will be useful,
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
11
|
+
# Lesser General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU Lesser General Public
|
14
|
+
# License along with this library; if not, write to the Free Software
|
15
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
16
|
+
|
17
|
+
require "gobject-introspection/collection-reader"
|
18
|
+
|
19
|
+
module GObjectIntrospection
|
20
|
+
class InterfaceInfo
|
21
|
+
extend CollectionReader
|
22
|
+
|
23
|
+
alias_method :__methods__, :methods
|
24
|
+
|
25
|
+
collection_reader("prerequisites")
|
26
|
+
collection_reader("properties")
|
27
|
+
collection_reader("methods")
|
28
|
+
collection_reader("signals")
|
29
|
+
collection_reader("vfuncs")
|
30
|
+
collection_reader("constants")
|
31
|
+
end
|
32
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (C) 2012 Ruby-GNOME2 Project Team
|
1
|
+
# Copyright (C) 2012-2013 Ruby-GNOME2 Project Team
|
2
2
|
#
|
3
3
|
# This library is free software; you can redistribute it and/or
|
4
4
|
# modify it under the terms of the GNU Lesser General Public
|
@@ -30,12 +30,20 @@ module GObjectIntrospection
|
|
30
30
|
def load(namespace)
|
31
31
|
repository = Repository.default
|
32
32
|
repository.require(namespace)
|
33
|
+
pre_load(repository, namespace)
|
33
34
|
repository.each(namespace) do |info|
|
34
35
|
load_info(info)
|
35
36
|
end
|
37
|
+
post_load(repository, namespace)
|
36
38
|
end
|
37
39
|
|
38
40
|
private
|
41
|
+
def pre_load(repository, namespace)
|
42
|
+
end
|
43
|
+
|
44
|
+
def post_load(repository, namespace)
|
45
|
+
end
|
46
|
+
|
39
47
|
def load_info(info)
|
40
48
|
case info
|
41
49
|
when FunctionInfo
|
@@ -56,23 +64,34 @@ module GObjectIntrospection
|
|
56
64
|
end
|
57
65
|
|
58
66
|
def load_function_info(info)
|
59
|
-
@base_module.
|
60
|
-
|
61
|
-
|
67
|
+
define_module_function(@base_module, info.name, info)
|
68
|
+
end
|
69
|
+
|
70
|
+
def define_module_function(target_module, name, function_info)
|
71
|
+
target_module.module_eval do
|
72
|
+
define_method(name) do |*arguments, &block|
|
73
|
+
function_info.invoke(*arguments, &block)
|
62
74
|
end
|
63
|
-
module_function(
|
75
|
+
module_function(name)
|
64
76
|
end
|
65
77
|
end
|
66
78
|
|
79
|
+
def define_struct(info, options={})
|
80
|
+
if info.gtype == GLib::Type::NONE
|
81
|
+
klass = self.class.define_struct(info.size, info.name, @base_module,
|
82
|
+
:parent => options[:parent])
|
83
|
+
else
|
84
|
+
klass = self.class.define_class(info.gtype, info.name, @base_module,
|
85
|
+
:parent => options[:parent])
|
86
|
+
end
|
87
|
+
load_fields(info, klass)
|
88
|
+
load_methods(info, klass)
|
89
|
+
end
|
90
|
+
|
67
91
|
def load_struct_info(info)
|
68
92
|
return if info.gtype_struct?
|
69
|
-
return if info.gtype == GLib::Type::NONE
|
70
93
|
|
71
|
-
|
72
|
-
load_field_infos(info, klass)
|
73
|
-
info.methods.each do |method_info|
|
74
|
-
load_method_info(method_info, klass)
|
75
|
-
end
|
94
|
+
define_struct(info)
|
76
95
|
end
|
77
96
|
|
78
97
|
def load_enum_info(info)
|
@@ -81,13 +100,11 @@ module GObjectIntrospection
|
|
81
100
|
|
82
101
|
def load_object_info(info)
|
83
102
|
klass = self.class.define_class(info.gtype, info.name, @base_module)
|
84
|
-
|
85
|
-
info
|
86
|
-
load_method_info(method_info, klass)
|
87
|
-
end
|
103
|
+
load_fields(info, klass)
|
104
|
+
load_methods(info, klass)
|
88
105
|
end
|
89
106
|
|
90
|
-
def
|
107
|
+
def load_fields(info, klass)
|
91
108
|
info.n_fields.times do |i|
|
92
109
|
field_info = info.get_field(i)
|
93
110
|
name = field_info.name
|
@@ -107,33 +124,124 @@ module GObjectIntrospection
|
|
107
124
|
end
|
108
125
|
end
|
109
126
|
|
110
|
-
def
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
127
|
+
def load_methods(info, klass)
|
128
|
+
grouped_methods = info.methods.group_by do |method_info|
|
129
|
+
method_info.class
|
130
|
+
end
|
131
|
+
grouped_methods.each do |method_info_class, method_infos|
|
132
|
+
next if method_infos.empty?
|
133
|
+
case method_infos.first
|
134
|
+
when ConstructorInfo
|
135
|
+
load_constructor_infos(method_infos, klass)
|
136
|
+
when MethodInfo
|
137
|
+
load_method_infos(method_infos, klass)
|
138
|
+
when FunctionInfo
|
139
|
+
load_function_infos(method_infos, klass)
|
118
140
|
else
|
119
|
-
|
141
|
+
raise "TODO: #{method_info_class}"
|
120
142
|
end
|
121
|
-
|
122
|
-
|
123
|
-
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def load_constructor_infos(infos, klass)
|
147
|
+
return if infos.empty?
|
148
|
+
|
149
|
+
validate = lambda do |info, arguments|
|
150
|
+
validate_arguments(info, arguments)
|
151
|
+
end
|
152
|
+
infos.each do |info|
|
153
|
+
name = "initialize_#{info.name}"
|
154
|
+
klass.__send__(:define_method, name) do |*arguments, &block|
|
155
|
+
validate.call(info, arguments, &block)
|
156
|
+
info.invoke(self, *arguments, &block)
|
124
157
|
end
|
158
|
+
end
|
159
|
+
|
160
|
+
find_info = lambda do |arguments|
|
161
|
+
find_suitable_callable_info(infos, arguments)
|
162
|
+
end
|
163
|
+
klass.__send__(:define_method, "initialize") do |*arguments, &block|
|
164
|
+
info = find_info.call(arguments, &block)
|
165
|
+
__send__("initialize_#{info.name}", *arguments, &block)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
def validate_arguments(info, arguments)
|
170
|
+
if arguments.size != info.n_in_args
|
171
|
+
details = "#{arguments.size} for #{info.n_in_args}"
|
172
|
+
raise ArgumentError, "wrong number of arguments (#{detail})"
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def find_suitable_callable_info(infos, arguments)
|
177
|
+
min_n_args = nil
|
178
|
+
max_n_args = nil
|
179
|
+
infos.each do |info|
|
180
|
+
if arguments.size == info.n_in_args
|
181
|
+
return info
|
182
|
+
end
|
183
|
+
n_in_args = info.n_in_args
|
184
|
+
min_n_args = [min_n_args || n_in_args, n_in_args].min
|
185
|
+
max_n_args = [max_n_args || n_in_args, n_in_args].max
|
186
|
+
end
|
187
|
+
detail = "#{arguments.size} for #{min_n_args}"
|
188
|
+
if min_n_args < max_n_args
|
189
|
+
detail << "..#{max_n_args}"
|
190
|
+
end
|
191
|
+
raise ArgumentError, "wrong number of arguments (#{detail})"
|
192
|
+
end
|
193
|
+
|
194
|
+
def rubyish_method_name(method_info)
|
195
|
+
name = method_info.name
|
196
|
+
return_type = method_info.return_type
|
197
|
+
if return_type.tag == GObjectIntrospection::TypeTag::BOOLEAN
|
198
|
+
case name
|
199
|
+
when /\A(?:is|get_is|get)_/
|
200
|
+
"#{$POSTMATCH}?"
|
201
|
+
when /\A(?:has|use)_/
|
202
|
+
"#{name}?"
|
203
|
+
else
|
204
|
+
name
|
205
|
+
end
|
206
|
+
elsif /\Aget_/ =~ name and method_info.n_in_args.zero?
|
207
|
+
$POSTMATCH
|
125
208
|
else
|
126
|
-
|
127
|
-
|
209
|
+
name
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
def load_method_infos(infos, klass)
|
214
|
+
infos.each do |info|
|
215
|
+
method_name = rubyish_method_name(info)
|
216
|
+
load_method_info(info, klass, method_name)
|
217
|
+
if /\Aset_/ =~ method_name and info.n_args == 1
|
218
|
+
klass.__send__(:alias_method, "#{$POSTMATCH}=", method_name)
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
def load_method_info(info, klass, method_name)
|
224
|
+
klass.__send__(:define_method, method_name) do |*arguments, &block|
|
225
|
+
info.invoke(self, *arguments, &block)
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
def load_function_infos(infos, klass)
|
230
|
+
infos.each do |info|
|
231
|
+
name = info.name
|
232
|
+
next if name == "new"
|
233
|
+
next if name == "alloc"
|
128
234
|
singleton_class = (class << klass; self; end)
|
129
|
-
singleton_class.__send__(:define_method, name) do |*arguments|
|
130
|
-
info.invoke(*arguments)
|
235
|
+
singleton_class.__send__(:define_method, name) do |*arguments, &block|
|
236
|
+
info.invoke(*arguments, &block)
|
131
237
|
end
|
132
238
|
end
|
133
239
|
end
|
134
240
|
|
135
241
|
def load_interface_info(info)
|
136
|
-
|
242
|
+
interface_module =
|
243
|
+
self.class.define_interface(info.gtype, info.name, @base_module)
|
244
|
+
load_methods(info, interface_module)
|
137
245
|
end
|
138
246
|
|
139
247
|
def load_constant_info(info)
|
@@ -142,7 +250,8 @@ module GObjectIntrospection
|
|
142
250
|
|
143
251
|
def load_union_info(info)
|
144
252
|
klass = self.class.define_class(info.gtype, info.name, @base_module)
|
145
|
-
|
253
|
+
load_fields(info, klass)
|
254
|
+
load_methods(info, klass)
|
146
255
|
end
|
147
256
|
end
|
148
257
|
end
|