gir_ffi 0.6.3 → 0.6.4
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +11 -0
- data/README.md +24 -6
- data/lib/ffi-glib/ptr_array.rb +17 -1
- data/lib/ffi-glib/variant.rb +15 -0
- data/lib/ffi-glib.rb +1 -0
- data/lib/ffi-gobject/object.rb +1 -1
- data/lib/ffi-gobject/ruby_closure.rb +1 -1
- data/lib/ffi-gobject/value.rb +13 -3
- data/lib/ffi-gobject.rb +1 -2
- data/lib/ffi-gobject_introspection/i_enum_info.rb +14 -0
- data/lib/ffi-gobject_introspection/lib.rb +2 -0
- data/lib/gir_ffi/arg_helper.rb +2 -0
- data/lib/gir_ffi/argument_builder.rb +22 -21
- data/lib/gir_ffi/base_argument_builder.rb +2 -1
- data/lib/gir_ffi/builder/module.rb +2 -3
- data/lib/gir_ffi/builder/type/enum.rb +18 -1
- data/lib/gir_ffi/builder/type/object.rb +20 -18
- data/lib/gir_ffi/class_base.rb +0 -1
- data/lib/gir_ffi/enum_base.rb +25 -0
- data/lib/gir_ffi/ffi_ext.rb +1 -0
- data/lib/gir_ffi/function_builder.rb +50 -33
- data/lib/gir_ffi/in_out_pointer.rb +0 -5
- data/lib/gir_ffi/in_pointer.rb +7 -5
- data/lib/gir_ffi/info_ext/i_callable_info.rb +4 -0
- data/lib/gir_ffi/info_ext/i_enum_info.rb +13 -0
- data/lib/gir_ffi/info_ext/i_field_info.rb +1 -1
- data/lib/gir_ffi/info_ext/i_object_info.rb +11 -0
- data/lib/gir_ffi/info_ext/i_registered_type_info.rb +11 -0
- data/lib/gir_ffi/info_ext/i_struct_info.rb +11 -0
- data/lib/gir_ffi/info_ext/i_type_info.rb +10 -19
- data/lib/gir_ffi/info_ext/i_union_info.rb +12 -0
- data/lib/gir_ffi/info_ext/safe_constant_name.rb +0 -2
- data/lib/gir_ffi/info_ext.rb +4 -0
- data/lib/gir_ffi/interface_base.rb +0 -1
- data/lib/gir_ffi/return_value_builder.rb +3 -2
- data/lib/gir_ffi/type_map.rb +3 -0
- data/lib/gir_ffi/version.rb +1 -1
- data/lib/gir_ffi/zero_terminated.rb +36 -3
- data/lib/gir_ffi-base/gir_ffi/library.rb +17 -0
- data/lib/gir_ffi-base/gobject/lib.rb +2 -2
- data/lib/gir_ffi.rb +1 -0
- data/tasks/test.rake +1 -0
- data/test/base_test_helper.rb +22 -2
- data/test/ffi-glib/ruby_closure_test.rb +1 -1
- data/test/ffi-glib/variant_test.rb +10 -0
- data/test/ffi-gobject/value_test.rb +24 -8
- data/test/ffi-gobject_introspection/i_enum_info_test.rb +17 -0
- data/test/gir_ffi/argument_builder_test.rb +66 -24
- data/test/gir_ffi/builder_test.rb +1 -1
- data/test/gir_ffi/function_builder_test.rb +1 -3
- data/test/gir_ffi/in_out_pointer_test.rb +5 -3
- data/test/gir_ffi/in_pointer_test.rb +32 -2
- data/test/gir_ffi/info_ext/i_arg_info_test.rb +2 -2
- data/test/gir_ffi/info_ext/i_callable_info_test.rb +2 -2
- data/test/gir_ffi/info_ext/i_field_info_test.rb +14 -20
- data/test/gir_ffi/info_ext/i_function_info_test.rb +2 -2
- data/test/gir_ffi/info_ext/i_signal_info_test.rb +2 -2
- data/test/gir_ffi/info_ext/i_type_info_test.rb +8 -8
- data/test/gir_ffi/info_ext/safe_constant_name_test.rb +2 -2
- data/test/gir_ffi/info_ext/safe_function_name_test.rb +2 -2
- data/test/gir_ffi/return_value_builder_test.rb +18 -1
- data/test/gir_ffi/zero_terminated_test.rb +10 -0
- data/test/gir_ffi_test_helper.rb +0 -19
- data/test/integration/generated_gimarshallingtests_test.rb +291 -99
- data/test/integration/generated_regress_test.rb +138 -14
- data/test/lib/autogen.sh +6 -2
- metadata +14 -2
data/History.txt
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
== 0.6.4 / 2013-06-30
|
2
|
+
|
3
|
+
* Represent enum types by modules wrapping FFI::Enum
|
4
|
+
* Support functions on enums
|
5
|
+
* Handle zero-terminated arrays of types other than int32
|
6
|
+
* Add override for GLib::Variant#get_string
|
7
|
+
* Handle non-throwing arguments and return values of type GError
|
8
|
+
* Handle arguments and return values of type GPtrArray
|
9
|
+
* Handle caller-allocated arguments of type GArray
|
10
|
+
* Deprecate GObject::Value#ruby_value, replacing it with #get_value
|
11
|
+
|
1
12
|
== 0.6.3 / 2013-06-15
|
2
13
|
|
3
14
|
* Make use of enums as element type for GHashTable and other containers
|
data/README.md
CHANGED
@@ -20,12 +20,18 @@ Ruby bindings for GNOME using the GObject Introspection Repository.
|
|
20
20
|
|
21
21
|
require 'gir_ffi'
|
22
22
|
|
23
|
-
|
23
|
+
# Set up the namespace you wish to use
|
24
|
+
GirFFI.setup :Gio
|
24
25
|
|
25
|
-
|
26
|
+
# Create an object
|
27
|
+
inet_address = Gio::InetAddress.new_from_string "127.0.0.1"
|
26
28
|
|
27
|
-
|
28
|
-
|
29
|
+
# Call some methods on the object
|
30
|
+
inet_address.is_loopback # => true
|
31
|
+
inet_address.is_multicast # => false
|
32
|
+
|
33
|
+
# Call a function in the namespace
|
34
|
+
Gio.dbus_is_name "foo" # => false
|
29
35
|
|
30
36
|
## Install
|
31
37
|
|
@@ -33,8 +39,8 @@ Ruby bindings for GNOME using the GObject Introspection Repository.
|
|
33
39
|
|
34
40
|
## Requirements
|
35
41
|
|
36
|
-
GirFFI should work on MRI 1.8
|
37
|
-
modes
|
42
|
+
GirFFI should work on MRI 1.8, 1.9 and 2.0, JRuby in both 1.8 and 1.9
|
43
|
+
modes, and on Rubinius in both 1.8 and 1.9 modes.
|
38
44
|
|
39
45
|
You will also need gobject-introspection installed with some
|
40
46
|
introspection data.
|
@@ -53,6 +59,18 @@ On Debian and Ubuntu, installing `libgirepository1.0-dev` and
|
|
53
59
|
|
54
60
|
GirFFI has not been tested on Mac OS X or Microsoft Windows. YMMV.
|
55
61
|
|
62
|
+
## Overrides
|
63
|
+
|
64
|
+
Sometimes, the GIR data is incorrect, or not detailed enough, and a
|
65
|
+
reasonable binding cannot be created automatically. For these cases,
|
66
|
+
overrides can be defined. The following gems with overrides
|
67
|
+
already exist:
|
68
|
+
|
69
|
+
* `gir_ffi-gtk`: overrides for Gtk+ 2 and 3.
|
70
|
+
* `gir_ffi-cairo`: overrides for Cairo
|
71
|
+
* `gir_ffi-pango`: overrides for Pango
|
72
|
+
* `gir_ffi-tracker`: overrides for Tracker
|
73
|
+
|
56
74
|
## Hacking and contributing
|
57
75
|
|
58
76
|
If you want to help out, have a look at TODO.rdoc, and check the notes
|
data/lib/ffi-glib/ptr_array.rb
CHANGED
@@ -15,10 +15,22 @@ module GLib
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def self.new type
|
18
|
-
wrap(Lib.g_ptr_array_new)
|
18
|
+
wrap(type, Lib.g_ptr_array_new)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.wrap type, ptr
|
22
|
+
super(ptr).tap {|it|
|
19
23
|
it.element_type = type}
|
20
24
|
end
|
21
25
|
|
26
|
+
def self.from type, it
|
27
|
+
case it
|
28
|
+
when self then it
|
29
|
+
when FFI::Pointer then wrap type, it
|
30
|
+
else self.new(type).tap {|arr| arr.add_array it}
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
22
34
|
def self.add array, data
|
23
35
|
array.add data
|
24
36
|
end
|
@@ -28,6 +40,10 @@ module GLib
|
|
28
40
|
Lib.g_ptr_array_add self, ptr
|
29
41
|
end
|
30
42
|
|
43
|
+
def add_array ary
|
44
|
+
ary.each {|item| add item}
|
45
|
+
end
|
46
|
+
|
31
47
|
# Re-implementation of the g_ptr_array_index macro
|
32
48
|
def index idx
|
33
49
|
sz = FFI.type_size :pointer
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module GLib
|
2
|
+
load_class :Variant
|
3
|
+
|
4
|
+
# Overrides for GVariant, GLib's variant data type.
|
5
|
+
class Variant
|
6
|
+
setup_instance_method "get_string"
|
7
|
+
|
8
|
+
def get_string_with_override
|
9
|
+
get_string_without_override.first
|
10
|
+
end
|
11
|
+
|
12
|
+
alias get_string_without_override get_string
|
13
|
+
alias get_string get_string_with_override
|
14
|
+
end
|
15
|
+
end
|
data/lib/ffi-glib.rb
CHANGED
data/lib/ffi-gobject/object.rb
CHANGED
@@ -43,7 +43,7 @@ module GObject
|
|
43
43
|
rclosure = wrap(closure.to_ptr)
|
44
44
|
|
45
45
|
args = n_param_values.times.map {|idx|
|
46
|
-
Value.wrap(param_values.to_ptr + idx * Value::Struct.size).
|
46
|
+
Value.wrap(param_values.to_ptr + idx * Value::Struct.size).get_value
|
47
47
|
}
|
48
48
|
|
49
49
|
result = rclosure.invoke_block(*args)
|
data/lib/ffi-gobject/value.rb
CHANGED
@@ -15,6 +15,7 @@ module GObject
|
|
15
15
|
TYPE_TO_SET_METHOD_MAP = {
|
16
16
|
TYPE_BOOLEAN => :set_boolean,
|
17
17
|
TYPE_INT => :set_int,
|
18
|
+
TYPE_INT64 => :set_int64,
|
18
19
|
TYPE_STRING => :set_string,
|
19
20
|
TYPE_FLOAT => :set_float,
|
20
21
|
TYPE_DOUBLE => :set_double,
|
@@ -25,6 +26,10 @@ module GObject
|
|
25
26
|
TYPE_ENUM => :set_enum
|
26
27
|
}
|
27
28
|
|
29
|
+
def value= val
|
30
|
+
set_value val
|
31
|
+
end
|
32
|
+
|
28
33
|
def set_value val
|
29
34
|
send set_method, val
|
30
35
|
self
|
@@ -62,6 +67,7 @@ module GObject
|
|
62
67
|
TYPE_TO_GET_METHOD_MAP = {
|
63
68
|
TYPE_BOOLEAN => :get_boolean,
|
64
69
|
TYPE_INT => :get_int,
|
70
|
+
TYPE_INT64 => :get_int64,
|
65
71
|
TYPE_STRING => :get_string,
|
66
72
|
TYPE_FLOAT => :get_float,
|
67
73
|
TYPE_DOUBLE => :get_double,
|
@@ -70,11 +76,15 @@ module GObject
|
|
70
76
|
TYPE_POINTER => :get_pointer
|
71
77
|
}
|
72
78
|
|
73
|
-
|
74
|
-
def ruby_value
|
79
|
+
def get_value
|
75
80
|
send get_method
|
76
81
|
end
|
77
82
|
|
83
|
+
# @deprecated Compatibility function. Remove in 0.7.0.
|
84
|
+
def ruby_value
|
85
|
+
get_value
|
86
|
+
end
|
87
|
+
|
78
88
|
class << self
|
79
89
|
# TODO: Give more generic name
|
80
90
|
def wrap_ruby_value val
|
@@ -94,7 +104,7 @@ module GObject
|
|
94
104
|
|
95
105
|
def for_g_type g_type
|
96
106
|
return nil if g_type == TYPE_NONE
|
97
|
-
self.new.
|
107
|
+
self.new.init g_type
|
98
108
|
end
|
99
109
|
end
|
100
110
|
|
data/lib/ffi-gobject.rb
CHANGED
@@ -109,8 +109,7 @@ module GObject
|
|
109
109
|
attach_function :g_hash_table_get_type, [], :size_t
|
110
110
|
|
111
111
|
attach_function :g_signal_connect_data,
|
112
|
-
[:pointer, :string, Callback, :pointer, ClosureNotify,
|
113
|
-
ConnectFlags],
|
112
|
+
[:pointer, :string, Callback, :pointer, ClosureNotify, ConnectFlags],
|
114
113
|
:ulong
|
115
114
|
attach_function :g_closure_set_marshal,
|
116
115
|
[:pointer, ClosureMarshal], :void
|
@@ -11,6 +11,20 @@ module GObjectIntrospection
|
|
11
11
|
##
|
12
12
|
build_array_method :values
|
13
13
|
|
14
|
+
def get_n_methods
|
15
|
+
Lib.g_enum_info_get_n_methods @gobj
|
16
|
+
end
|
17
|
+
def get_method(index)
|
18
|
+
IFunctionInfo.wrap(Lib.g_enum_info_get_method @gobj, index)
|
19
|
+
end
|
20
|
+
|
21
|
+
##
|
22
|
+
build_array_method :get_methods
|
23
|
+
|
24
|
+
def find_method name
|
25
|
+
get_methods.find {|m| m.name == name}
|
26
|
+
end
|
27
|
+
|
14
28
|
def storage_type
|
15
29
|
Lib.g_enum_info_get_storage_type @gobj
|
16
30
|
end
|
@@ -178,6 +178,8 @@ module GObjectIntrospection
|
|
178
178
|
attach_function :g_enum_info_get_storage_type, [:pointer], :ITypeTag
|
179
179
|
attach_function :g_enum_info_get_n_values, [:pointer], :int
|
180
180
|
attach_function :g_enum_info_get_value, [:pointer, :int], :pointer
|
181
|
+
attach_function :g_enum_info_get_n_methods, [:pointer], :int
|
182
|
+
attach_function :g_enum_info_get_method, [:pointer, :int], :pointer
|
181
183
|
|
182
184
|
# IObjectInfo
|
183
185
|
attach_function :g_object_info_get_type_name, [:pointer], :string
|
data/lib/gir_ffi/arg_helper.rb
CHANGED
@@ -53,8 +53,6 @@ module GirFFI
|
|
53
53
|
else
|
54
54
|
"#{argument_class_name}.wrap(#{output_conversion_arguments})"
|
55
55
|
end
|
56
|
-
elsif is_fixed_length_array?
|
57
|
-
"GLib::SizedArray.wrap(#{subtype_tag_or_class_name}, #{array_size}, #{callarg}.to_value)"
|
58
56
|
else
|
59
57
|
"#{callarg}.to_value"
|
60
58
|
end
|
@@ -68,10 +66,6 @@ module GirFFI
|
|
68
66
|
specialized_type_tag == :c && type_info.array_fixed_size > -1
|
69
67
|
end
|
70
68
|
|
71
|
-
def is_fixed_length_array?
|
72
|
-
specialized_type_tag == :c
|
73
|
-
end
|
74
|
-
|
75
69
|
def fixed_array_size_check
|
76
70
|
size = type_info.array_fixed_size
|
77
71
|
"GirFFI::ArgHelper.check_fixed_array_size #{size}, #{@name}, \"#{@name}\""
|
@@ -93,7 +87,11 @@ module GirFFI
|
|
93
87
|
def set_function_call_argument
|
94
88
|
value = if @direction == :out
|
95
89
|
if is_caller_allocated_object?
|
96
|
-
|
90
|
+
if specialized_type_tag == :array
|
91
|
+
"#{argument_class_name}.new #{elm_t}"
|
92
|
+
else
|
93
|
+
"#{argument_class_name}.new"
|
94
|
+
end
|
97
95
|
else
|
98
96
|
"GirFFI::InOutPointer.for #{specialized_type_tag.inspect}"
|
99
97
|
end
|
@@ -108,42 +106,45 @@ module GirFFI
|
|
108
106
|
end
|
109
107
|
|
110
108
|
def is_caller_allocated_object?
|
111
|
-
[:
|
109
|
+
[ :struct, :array ].include?(specialized_type_tag) &&
|
112
110
|
@arginfo.caller_allocates?
|
113
111
|
end
|
114
112
|
|
115
113
|
def needs_outgoing_parameter_conversion?
|
116
|
-
[ :array, :enum, :flags, :ghash, :glist, :gslist, :object,
|
117
|
-
:strv, :utf8 ].include?(specialized_type_tag)
|
114
|
+
[ :array, :c, :enum, :error, :flags, :ghash, :glist, :gslist, :object,
|
115
|
+
:ptr_array, :struct, :strv, :utf8 ].include?(specialized_type_tag)
|
118
116
|
end
|
119
117
|
|
120
118
|
def needs_ingoing_parameter_conversion?
|
121
119
|
@direction == :inout ||
|
122
|
-
[ :
|
123
|
-
:
|
120
|
+
[ :array, :c, :callback, :ghash, :glist, :gslist, :object, :ptr_array,
|
121
|
+
:struct, :strv, :utf8, :void, :zero_terminated ].include?(specialized_type_tag)
|
124
122
|
end
|
125
123
|
|
126
124
|
def ingoing_parameter_conversion
|
127
125
|
case specialized_type_tag
|
128
126
|
when :enum, :flags
|
129
127
|
base = "#{argument_class_name}[#{parameter_conversion_arguments}]"
|
130
|
-
|
131
|
-
|
132
|
-
:zero_terminated, :strv, :callback, :utf8, :c
|
128
|
+
when :array, :c, :callback, :ghash, :glist, :gslist, :object, :ptr_array,
|
129
|
+
:struct, :strv, :utf8, :void, :zero_terminated
|
133
130
|
base = "#{argument_class_name}.from(#{parameter_conversion_arguments})"
|
134
|
-
if has_output_value?
|
135
|
-
"GirFFI::InOutPointer.from :pointer, #{base}"
|
136
|
-
else
|
137
|
-
base
|
138
|
-
end
|
139
131
|
else
|
140
132
|
base = "#{parameter_conversion_arguments}"
|
133
|
+
end
|
134
|
+
|
135
|
+
if has_output_value?
|
141
136
|
"GirFFI::InOutPointer.from #{specialized_type_tag.inspect}, #{base}"
|
137
|
+
else
|
138
|
+
base
|
142
139
|
end
|
143
140
|
end
|
144
141
|
|
145
142
|
def output_conversion_arguments
|
146
|
-
|
143
|
+
if specialized_type_tag == :c
|
144
|
+
"#{subtype_tag_or_class_name}, #{array_size}, #{callarg}.to_value"
|
145
|
+
else
|
146
|
+
conversion_arguments "#{callarg}.to_value"
|
147
|
+
end
|
147
148
|
end
|
148
149
|
|
149
150
|
def parameter_conversion_arguments
|
@@ -42,6 +42,7 @@ module GirFFI
|
|
42
42
|
:byte_array => 'GLib::ByteArray',
|
43
43
|
:c => 'GLib::SizedArray',
|
44
44
|
:callback => 'GirFFI::Callback',
|
45
|
+
:error => 'GLib::Error',
|
45
46
|
:ghash => 'GLib::HashTable',
|
46
47
|
:glist => 'GLib::List',
|
47
48
|
:gslist => 'GLib::SList',
|
@@ -118,7 +119,7 @@ module GirFFI
|
|
118
119
|
"#{specialized_type_tag.inspect}, #{name}"
|
119
120
|
when :c
|
120
121
|
"#{subtype_tag_or_class_name}, #{type_info.array_fixed_size}, #{name}"
|
121
|
-
when :
|
122
|
+
when :array, :ghash, :glist, :gslist, :ptr_array, :zero_terminated
|
122
123
|
"#{elm_t}, #{name}"
|
123
124
|
when :callback
|
124
125
|
iface = type_info.interface
|
@@ -80,8 +80,8 @@ module GirFFI
|
|
80
80
|
def setup_lib_for_ffi
|
81
81
|
@lib = get_or_define_module @module, :Lib
|
82
82
|
|
83
|
-
unless (class << @lib; self.include?
|
84
|
-
@lib.extend
|
83
|
+
unless (class << @lib; self.include? GirFFI::Library; end)
|
84
|
+
@lib.extend GirFFI::Library
|
85
85
|
@lib.ffi_lib_flags :global, :lazy
|
86
86
|
libspec = gir.shared_library(@namespace)
|
87
87
|
unless libspec.nil?
|
@@ -123,6 +123,5 @@ module GirFFI
|
|
123
123
|
def get_or_define_module parent, name
|
124
124
|
optionally_define_constant(parent, name) { Module.new }
|
125
125
|
end
|
126
|
-
|
127
126
|
end
|
128
127
|
end
|
@@ -1,4 +1,6 @@
|
|
1
1
|
require 'gir_ffi/builder/type/registered_type'
|
2
|
+
require 'gir_ffi/builder/type/with_methods'
|
3
|
+
require 'gir_ffi/enum_base'
|
2
4
|
|
3
5
|
module GirFFI
|
4
6
|
module Builder
|
@@ -8,6 +10,8 @@ module GirFFI
|
|
8
10
|
# attached to the appropriate namespace module, and will be defined
|
9
11
|
# as an enum for FFI.
|
10
12
|
class Enum < RegisteredType
|
13
|
+
include WithMethods
|
14
|
+
|
11
15
|
private
|
12
16
|
|
13
17
|
def enum_sym
|
@@ -22,11 +26,15 @@ module GirFFI
|
|
22
26
|
end
|
23
27
|
|
24
28
|
def instantiate_class
|
25
|
-
@klass =
|
29
|
+
@klass = get_or_define_module namespace_module, @classname
|
30
|
+
@enum = optionally_define_constant @klass, :Enum do
|
26
31
|
lib.enum(enum_sym, value_spec)
|
27
32
|
end
|
28
33
|
unless already_set_up
|
34
|
+
@klass.extend superclass
|
35
|
+
setup_constants
|
29
36
|
setup_gtype_getter
|
37
|
+
stub_methods
|
30
38
|
setup_inspect
|
31
39
|
end
|
32
40
|
end
|
@@ -42,6 +50,15 @@ module GirFFI
|
|
42
50
|
def already_set_up
|
43
51
|
@klass.respond_to? :get_gtype
|
44
52
|
end
|
53
|
+
|
54
|
+
def superclass
|
55
|
+
@superclass ||= EnumBase
|
56
|
+
end
|
57
|
+
|
58
|
+
# FIXME: Remove duplication with Builder::Module
|
59
|
+
def get_or_define_module parent, name
|
60
|
+
optionally_define_constant(parent, name) { ::Module.new }
|
61
|
+
end
|
45
62
|
end
|
46
63
|
end
|
47
64
|
end
|
@@ -51,7 +51,7 @@ module GirFFI
|
|
51
51
|
setup_interfaces
|
52
52
|
end
|
53
53
|
|
54
|
-
# FIXME: Private method only in subclass
|
54
|
+
# FIXME: Private method only used in subclass
|
55
55
|
def layout_superclass
|
56
56
|
FFI::Struct
|
57
57
|
end
|
@@ -69,16 +69,14 @@ module GirFFI
|
|
69
69
|
end
|
70
70
|
|
71
71
|
def superclass
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
end
|
78
|
-
end
|
79
|
-
@superclass
|
72
|
+
@superclass ||= if parent
|
73
|
+
Builder.build_class parent
|
74
|
+
else
|
75
|
+
ObjectBase
|
76
|
+
end
|
80
77
|
end
|
81
78
|
|
79
|
+
# TODO: Unify with field accessor setup.
|
82
80
|
def setup_property_accessors
|
83
81
|
info.properties.each do |prop|
|
84
82
|
setup_accessors_for_property_info prop
|
@@ -94,20 +92,24 @@ module GirFFI
|
|
94
92
|
end
|
95
93
|
|
96
94
|
# TODO: Guard agains accidental invocation of undefined vfuncs.
|
95
|
+
# TODO: Create object responsible for creating these invokers
|
97
96
|
def setup_vfunc_invokers
|
98
97
|
info.vfuncs.each do |vfinfo|
|
99
|
-
invoker = vfinfo.invoker
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
@klass.class_eval "
|
104
|
-
def #{vfinfo.name} *args, &block
|
105
|
-
#{invoker.name}(*args, &block)
|
106
|
-
end
|
107
|
-
"
|
98
|
+
if (invoker = vfinfo.invoker)
|
99
|
+
define_vfunc_invoker vfinfo.name, invoker.name
|
100
|
+
end
|
108
101
|
end
|
109
102
|
end
|
110
103
|
|
104
|
+
def define_vfunc_invoker vfunc_name, invoker_name
|
105
|
+
return if vfunc_name == invoker_name
|
106
|
+
@klass.class_eval "
|
107
|
+
def #{vfunc_name} *args, &block
|
108
|
+
#{invoker_name}(*args, &block)
|
109
|
+
end
|
110
|
+
"
|
111
|
+
end
|
112
|
+
|
111
113
|
def setup_interfaces
|
112
114
|
interfaces.each do |iface|
|
113
115
|
@klass.class_eval do
|
data/lib/gir_ffi/class_base.rb
CHANGED
@@ -0,0 +1,25 @@
|
|
1
|
+
module GirFFI
|
2
|
+
module EnumBase
|
3
|
+
def [](arg)
|
4
|
+
self::Enum[arg]
|
5
|
+
end
|
6
|
+
|
7
|
+
def setup_and_call method, *arguments, &block
|
8
|
+
result = setup_method method.to_s
|
9
|
+
|
10
|
+
unless result
|
11
|
+
raise RuntimeError, "Unable to set up method #{method} in #{self}"
|
12
|
+
end
|
13
|
+
|
14
|
+
self.send method, *arguments, &block
|
15
|
+
end
|
16
|
+
|
17
|
+
def gir_ffi_builder
|
18
|
+
self.const_get :GIR_FFI_BUILDER
|
19
|
+
end
|
20
|
+
|
21
|
+
def setup_method name
|
22
|
+
gir_ffi_builder.setup_method name
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'gir_ffi/ffi_ext/pointer'
|
@@ -15,81 +15,98 @@ module GirFFI
|
|
15
15
|
|
16
16
|
def generate
|
17
17
|
vargen = GirFFI::VariableNameGenerator.new
|
18
|
-
@
|
19
|
-
@
|
20
|
-
|
18
|
+
@argument_builders = @info.args.map {|arg| ArgumentBuilder.new vargen, arg }
|
19
|
+
@return_value_builder = ReturnValueBuilder.new(vargen, @info.return_type,
|
20
|
+
@info.constructor?)
|
21
21
|
|
22
|
-
|
22
|
+
link_array_length_arguments
|
23
|
+
setup_error_argument vargen
|
24
|
+
return filled_out_template
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def link_array_length_arguments
|
30
|
+
alldata = @argument_builders.dup << @return_value_builder
|
23
31
|
|
24
32
|
alldata.each {|data|
|
25
33
|
idx = data.type_info.array_length
|
26
34
|
if idx > -1
|
27
|
-
|
28
|
-
|
35
|
+
other_data = @argument_builders[idx]
|
36
|
+
data.length_arg = other_data
|
37
|
+
other_data.array_arg = data
|
29
38
|
end
|
30
39
|
}
|
31
|
-
|
32
|
-
setup_error_argument vargen
|
33
|
-
return filled_out_template
|
34
40
|
end
|
35
41
|
|
36
|
-
private
|
37
|
-
|
38
42
|
def setup_error_argument vargen
|
39
43
|
klass = @info.throws? ? ErrorArgumentBuilder : NullArgumentBuilder
|
40
44
|
@errarg = klass.new vargen, nil, nil, :error
|
41
45
|
end
|
42
46
|
|
43
47
|
def filled_out_template
|
44
|
-
lines = pre
|
45
|
-
lines << "#{capture}#{@libmodule}.#{@info.symbol} #{callargs.join(', ')}"
|
46
|
-
lines << post
|
47
|
-
|
48
48
|
meta = @info.method? ? '' : "self."
|
49
49
|
|
50
|
-
code = "def #{meta}#{@info.safe_name} #{
|
51
|
-
code <<
|
50
|
+
code = "def #{meta}#{@info.safe_name} #{method_arguments.join(', ')}\n"
|
51
|
+
code << method_body
|
52
52
|
code << "\nend\n"
|
53
53
|
end
|
54
54
|
|
55
|
-
def
|
56
|
-
|
55
|
+
def method_body
|
56
|
+
lines = preparation << function_call << post_processing << cleanup
|
57
|
+
lines << "return #{return_values.join(', ')}" if has_return_values?
|
58
|
+
lines.flatten.join("\n").indent
|
57
59
|
end
|
58
60
|
|
59
|
-
def
|
60
|
-
|
61
|
+
def function_call
|
62
|
+
"#{capture}#{@libmodule}.#{@info.symbol} #{function_call_arguments.join(', ')}"
|
63
|
+
end
|
64
|
+
|
65
|
+
def method_arguments
|
66
|
+
@argument_builders.map(&:inarg).compact
|
67
|
+
end
|
68
|
+
|
69
|
+
def function_call_arguments
|
70
|
+
ca = @argument_builders.map(&:callarg)
|
61
71
|
ca << @errarg.callarg
|
62
72
|
ca.unshift "self" if @info.method?
|
63
73
|
ca.compact
|
64
74
|
end
|
65
75
|
|
66
|
-
def
|
67
|
-
pr = @
|
76
|
+
def preparation
|
77
|
+
pr = @argument_builders.map(&:pre)
|
68
78
|
pr << @errarg.pre
|
69
79
|
pr.flatten
|
70
80
|
end
|
71
81
|
|
72
82
|
def capture
|
73
|
-
if (cv = @
|
83
|
+
if (cv = @return_value_builder.cvar)
|
74
84
|
"#{cv} = "
|
75
85
|
else
|
76
86
|
""
|
77
87
|
end
|
78
88
|
end
|
79
89
|
|
80
|
-
def
|
81
|
-
|
90
|
+
def post_processing
|
91
|
+
# FIXME: Sorting knows too much about internals of ArgumentBuilder.
|
92
|
+
args = @argument_builders.sort_by {|arg| arg.type_info.array_length}
|
93
|
+
args << @return_value_builder
|
94
|
+
args.unshift @errarg
|
82
95
|
|
83
|
-
|
84
|
-
|
85
|
-
po.unshift @errarg.post
|
96
|
+
args.map {|arg| arg.post}
|
97
|
+
end
|
86
98
|
|
87
|
-
|
99
|
+
def cleanup
|
100
|
+
@argument_builders.map {|item| item.cleanup}
|
101
|
+
end
|
88
102
|
|
89
|
-
|
90
|
-
|
103
|
+
def return_values
|
104
|
+
@return_values ||= ([@return_value_builder.retval] +
|
105
|
+
@argument_builders.map(&:retval)).compact
|
106
|
+
end
|
91
107
|
|
92
|
-
|
108
|
+
def has_return_values?
|
109
|
+
!return_values.empty?
|
93
110
|
end
|
94
111
|
end
|
95
112
|
end
|