gobject-introspection 1.1.9 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|