gir_ffi 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +9 -0
- data/Rakefile +0 -18
- data/TODO.rdoc +1 -1
- data/lib/gir_ffi/arg_helper.rb +165 -35
- data/lib/gir_ffi/builder.rb +4 -3
- data/lib/gir_ffi/class_base.rb +11 -3
- data/lib/gir_ffi/class_builder.rb +49 -35
- data/lib/gir_ffi/function_definition_builder.rb +194 -64
- data/lib/gir_ffi/i_arg_info.rb +3 -0
- data/lib/gir_ffi/i_callback_info.rb +1 -1
- data/lib/gir_ffi/i_interface_info.rb +67 -2
- data/lib/gir_ffi/i_repository.rb +5 -0
- data/lib/gir_ffi/lib.rb +22 -1
- data/lib/gir_ffi/module_builder.rb +1 -0
- data/lib/gir_ffi/overrides/gobject.rb +16 -13
- data/lib/gir_ffi/overrides/gtk.rb +1 -1
- data/tasks/notes.rake +12 -25
- data/tasks/setup.rb +0 -132
- data/tasks/test.rake +4 -12
- data/test/arg_helper_test.rb +25 -7
- data/test/builder_test.rb +36 -21
- data/test/class_base_test.rb +0 -7
- data/test/class_builder_test.rb +6 -0
- data/test/everything_test.rb +427 -1
- data/test/function_definition_builder_test.rb +69 -12
- data/test/gobject_overrides_test.rb +12 -3
- data/test/test_helper.rb +5 -0
- metadata +8 -10
- data/tasks/bones.rake +0 -87
- data/tasks/post_load.rake +0 -25
data/History.txt
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
== 0.0.5 / 2010-12-30
|
2
|
+
|
3
|
+
* Don't create instance methods out of functions and vice versa.
|
4
|
+
* Find signals on interfaces, too.
|
5
|
+
* Implement tests for most of Everything.
|
6
|
+
* Correctly handle array + size arguments.
|
7
|
+
* Handle most other argument types.
|
8
|
+
* Various internal changes and other fixes.
|
9
|
+
|
1
10
|
== 0.0.4 / 2010-12-14
|
2
11
|
|
3
12
|
* Lots of changes to the internals.
|
data/Rakefile
CHANGED
@@ -1,21 +1,3 @@
|
|
1
|
-
# Look in the tasks/setup.rb file for the various options that can be
|
2
|
-
# configured in this Rakefile. The .rake files in the tasks directory
|
3
|
-
# are where the options are used.
|
4
|
-
|
5
1
|
load 'tasks/setup.rb'
|
6
2
|
|
7
|
-
ensure_in_path 'lib'
|
8
|
-
require 'gir_ffi'
|
9
|
-
|
10
3
|
task :default => 'test:run'
|
11
|
-
|
12
|
-
PROJ.name = 'gir_ffi'
|
13
|
-
PROJ.authors = 'Matijs van Zuijlen'
|
14
|
-
PROJ.email = 'matijs@matijs.net'
|
15
|
-
PROJ.url = 'http://www.github.com/mvz/ruby-gir-ffi'
|
16
|
-
PROJ.version = GirFFI::VERSION
|
17
|
-
PROJ.readme_file = 'README.rdoc'
|
18
|
-
|
19
|
-
PROJ.exclude << ["^tmp/", "\\.swp$", "^\\.gitignore$", "^\\.autotest$"]
|
20
|
-
|
21
|
-
# EOF
|
data/TODO.rdoc
CHANGED
@@ -21,7 +21,7 @@ distinguished, based on the GIR data, from methods that take a pointer to
|
|
21
21
|
any GObject.
|
22
22
|
|
23
23
|
I'm currently passing the object id as the value of the 'gpointer'. Special
|
24
|
-
|
24
|
+
overrides will have to be used for the cases where the 'gpointer' actually
|
25
25
|
needs to be a GObject. I consider it an omission in GIRepository that these
|
26
26
|
two cases are not distinguished.
|
27
27
|
|
data/lib/gir_ffi/arg_helper.rb
CHANGED
@@ -8,68 +8,179 @@ module GirFFI
|
|
8
8
|
FFI::Pointer.new(obj.object_id)
|
9
9
|
end
|
10
10
|
|
11
|
+
def self.typed_array_to_inptr type, ary
|
12
|
+
return nil if ary.nil?
|
13
|
+
block = allocate_array_of_type type, ary.length
|
14
|
+
block.send "put_array_of_#{type}", 0, ary
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.int32_array_to_inptr ary
|
18
|
+
typed_array_to_inptr :int32, ary
|
19
|
+
end
|
20
|
+
|
21
|
+
# TODO: Use alias.
|
22
|
+
def self.int_array_to_inptr ary
|
23
|
+
int32_array_to_inptr ary
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.int16_array_to_inptr ary
|
27
|
+
typed_array_to_inptr :int16, ary
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.int64_array_to_inptr ary
|
31
|
+
typed_array_to_inptr :int64, ary
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.int8_array_to_inptr ary
|
35
|
+
typed_array_to_inptr :int8, ary
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.utf8_to_inptr str
|
39
|
+
return nil if str.nil?
|
40
|
+
len = str.bytesize
|
41
|
+
AllocationHelper.safe_malloc(len + 1).write_string(str).put_char(len, 0)
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.GType_array_to_inptr ary
|
45
|
+
case FFI.type_size(:size_t)
|
46
|
+
when 4
|
47
|
+
int32_array_to_inptr ary
|
48
|
+
when 8
|
49
|
+
int64_array_to_inptr ary
|
50
|
+
else
|
51
|
+
raise RuntimeError, "Unexpected size of :size_t"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.cleanup_ptr ptr
|
56
|
+
LibC.free ptr
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.cleanup_ptr_ptr ptr
|
60
|
+
block = ptr.read_pointer
|
61
|
+
LibC.free ptr
|
62
|
+
LibC.free block
|
63
|
+
end
|
64
|
+
|
65
|
+
# Takes an outptr to a pointer array, and frees all pointers.
|
66
|
+
def self.cleanup_ptr_array_ptr ptr, size
|
67
|
+
return if ptr.nil?
|
68
|
+
|
69
|
+
block = ptr.read_pointer
|
70
|
+
LibC.free ptr
|
71
|
+
|
72
|
+
return if block.null?
|
73
|
+
|
74
|
+
ptrs = block.read_array_of_pointer(size)
|
75
|
+
LibC.free block
|
76
|
+
|
77
|
+
ptrs.map do |p|
|
78
|
+
LibC.free p unless p.null?
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
11
82
|
def self.int_to_inoutptr val
|
12
|
-
|
13
|
-
|
14
|
-
|
83
|
+
int_pointer.write_int val
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.utf8_to_inoutptr str
|
87
|
+
sptr = utf8_to_inptr str
|
88
|
+
pointer_pointer.write_pointer sptr
|
15
89
|
end
|
16
90
|
|
17
|
-
def self.
|
91
|
+
def self.int_array_to_inoutptr ary
|
92
|
+
block = int_array_to_inptr ary
|
93
|
+
pointer_pointer.write_pointer block
|
94
|
+
end
|
95
|
+
|
96
|
+
def self.utf8_array_to_inoutptr ary
|
18
97
|
return nil if ary.nil?
|
19
98
|
|
20
|
-
ptrs = ary.map {|str|
|
21
|
-
len = str.bytesize
|
22
|
-
AllocationHelper.safe_malloc(len + 1).write_string(str).put_char(len, 0)
|
23
|
-
}
|
99
|
+
ptrs = ary.map {|str| utf8_to_inptr str}
|
24
100
|
|
25
|
-
|
26
|
-
block = AllocationHelper.safe_malloc ptr_size * ptrs.length
|
101
|
+
block = AllocationHelper.safe_malloc FFI.type_size(:pointer) * ptrs.length
|
27
102
|
block.write_array_of_pointer ptrs
|
28
103
|
|
29
|
-
|
30
|
-
argv.write_pointer block
|
31
|
-
argv
|
104
|
+
pointer_pointer.write_pointer block
|
32
105
|
end
|
33
106
|
|
34
107
|
def self.double_to_inoutptr val
|
35
|
-
|
36
|
-
|
37
|
-
|
108
|
+
double_pointer.put_double 0, val
|
109
|
+
end
|
110
|
+
|
111
|
+
def self.int_pointer
|
112
|
+
AllocationHelper.safe_malloc FFI.type_size(:int)
|
113
|
+
end
|
114
|
+
|
115
|
+
def self.double_pointer
|
116
|
+
AllocationHelper.safe_malloc FFI.type_size(:double)
|
117
|
+
end
|
118
|
+
|
119
|
+
def self.pointer_pointer
|
120
|
+
AllocationHelper.safe_malloc FFI.type_size(:pointer)
|
121
|
+
end
|
122
|
+
|
123
|
+
def self.int_outptr
|
124
|
+
int_pointer.write_int 0
|
38
125
|
end
|
39
126
|
|
40
|
-
|
127
|
+
def self.double_outptr
|
128
|
+
double_pointer.write_double 0.0
|
129
|
+
end
|
130
|
+
|
131
|
+
def self.pointer_outptr
|
132
|
+
pointer_pointer.write_pointer nil
|
133
|
+
end
|
134
|
+
|
135
|
+
def self.utf8_outptr
|
136
|
+
pointer_outptr
|
137
|
+
end
|
138
|
+
|
139
|
+
# Converts an outptr to a pointer.
|
140
|
+
def self.outptr_to_pointer ptr
|
141
|
+
ptr.read_pointer
|
142
|
+
end
|
143
|
+
|
144
|
+
# Converts an outptr to an int.
|
41
145
|
def self.outptr_to_int ptr
|
42
|
-
|
43
|
-
LibC.free ptr
|
44
|
-
value
|
146
|
+
ptr.read_int
|
45
147
|
end
|
46
148
|
|
47
|
-
# Converts an outptr to a string
|
48
|
-
def self.
|
149
|
+
# Converts an outptr to a string.
|
150
|
+
def self.outptr_to_utf8 ptr
|
49
151
|
return nil if ptr.nil?
|
152
|
+
sptr = ptr.read_pointer
|
50
153
|
|
51
|
-
|
52
|
-
|
154
|
+
sptr.null? ? nil : sptr.read_string
|
155
|
+
end
|
53
156
|
|
157
|
+
# Converts an outptr to a string array.
|
158
|
+
def self.outptr_to_utf8_array ptr, size
|
159
|
+
return nil if ptr.nil?
|
160
|
+
block = ptr.read_pointer
|
54
161
|
return nil if block.null?
|
55
|
-
|
56
162
|
ptrs = block.read_array_of_pointer(size)
|
57
|
-
LibC.free block
|
58
163
|
|
59
164
|
ptrs.map do |p|
|
60
|
-
|
61
|
-
nil
|
62
|
-
else
|
63
|
-
p.read_string.tap { LibC.free p }
|
64
|
-
end
|
165
|
+
p.null? ? nil : p.read_string
|
65
166
|
end
|
66
167
|
end
|
67
168
|
|
68
|
-
# Converts an outptr to a double
|
169
|
+
# Converts an outptr to a double.
|
69
170
|
def self.outptr_to_double ptr
|
70
|
-
|
71
|
-
|
72
|
-
|
171
|
+
ptr.get_double 0
|
172
|
+
end
|
173
|
+
|
174
|
+
# Converts an outptr to an array of int.
|
175
|
+
def self.outptr_to_int_array ptr, size
|
176
|
+
return nil if ptr.null?
|
177
|
+
block = ptr.read_pointer
|
178
|
+
return nil if block.null?
|
179
|
+
ptr_to_int_array block, size
|
180
|
+
end
|
181
|
+
|
182
|
+
def self.ptr_to_int_array ptr, size
|
183
|
+
ptr.read_array_of_int(size)
|
73
184
|
end
|
74
185
|
|
75
186
|
def self.mapped_callback_args prc=nil, &block
|
@@ -104,5 +215,24 @@ module GirFFI
|
|
104
215
|
GirFFI::GObject.object_ref_sink(gobject)
|
105
216
|
end
|
106
217
|
end
|
218
|
+
|
219
|
+
def self.check_fixed_array_size size, arr, name
|
220
|
+
unless arr.size == size
|
221
|
+
raise ArgumentError, "#{name} should have size #{size}"
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
def self.allocate_array_of_type type, length
|
226
|
+
AllocationHelper.safe_malloc FFI.type_size(type) * length
|
227
|
+
end
|
228
|
+
|
229
|
+
# FIXME: Quasi-circular dependency on generated module
|
230
|
+
def self.object_pointer_to_object optr
|
231
|
+
tp = ::GObject.type_from_instance_pointer optr
|
232
|
+
gir = GirFFI::IRepository.default
|
233
|
+
info = gir.find_by_gtype tp
|
234
|
+
klass = GirFFI::Builder.build_class info.namespace, info.name
|
235
|
+
klass.wrap optr
|
236
|
+
end
|
107
237
|
end
|
108
238
|
end
|
data/lib/gir_ffi/builder.rb
CHANGED
@@ -31,7 +31,8 @@ module GirFFI
|
|
31
31
|
|
32
32
|
def self.ffi_function_argument_types info
|
33
33
|
types = info.args.map do |a|
|
34
|
-
iarginfo_to_ffitype a
|
34
|
+
tp = iarginfo_to_ffitype a
|
35
|
+
tp == :string ? :pointer : tp
|
35
36
|
end
|
36
37
|
if info.type == :function
|
37
38
|
types.unshift :pointer if info.method?
|
@@ -65,8 +66,8 @@ module GirFFI
|
|
65
66
|
end
|
66
67
|
when :boolean
|
67
68
|
return :bool
|
68
|
-
when :GType
|
69
|
-
return :
|
69
|
+
when :GType, :size
|
70
|
+
return :size_t
|
70
71
|
else
|
71
72
|
return tag
|
72
73
|
end
|
data/lib/gir_ffi/class_base.rb
CHANGED
@@ -7,7 +7,6 @@ module GirFFI
|
|
7
7
|
def_delegators :@struct, :[], :[]=, :to_ptr
|
8
8
|
|
9
9
|
def initialize(*args)
|
10
|
-
# TODO: Handle NULL pointer.
|
11
10
|
@struct = ffi_structure.new(*args)
|
12
11
|
end
|
13
12
|
|
@@ -19,13 +18,13 @@ module GirFFI
|
|
19
18
|
self.class.gir_ffi_builder
|
20
19
|
end
|
21
20
|
|
22
|
-
def
|
21
|
+
def setup_and_call method, *arguments, &block
|
23
22
|
result = gir_ffi_builder.setup_instance_method method.to_s
|
24
23
|
return super unless result
|
25
24
|
self.send method, *arguments, &block
|
26
25
|
end
|
27
26
|
|
28
|
-
def self.
|
27
|
+
def self.setup_and_call method, *arguments, &block
|
29
28
|
result = gir_ffi_builder.setup_method method.to_s
|
30
29
|
return super unless result
|
31
30
|
self.send method, *arguments, &block
|
@@ -46,6 +45,15 @@ module GirFFI
|
|
46
45
|
|
47
46
|
alias_method :_real_new, :new
|
48
47
|
undef new
|
48
|
+
|
49
|
+
def wrap ptr
|
50
|
+
return nil if ptr.nil? or ptr.null?
|
51
|
+
_real_new ptr
|
52
|
+
end
|
53
|
+
|
54
|
+
def allocate
|
55
|
+
_real_new
|
56
|
+
end
|
49
57
|
end
|
50
58
|
end
|
51
59
|
end
|
@@ -14,21 +14,18 @@ module GirFFI
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def setup_method method
|
17
|
-
definition = prepare_method method.to_s
|
18
|
-
|
19
|
-
return false if definition.nil?
|
20
|
-
|
21
17
|
klass = build_class
|
22
18
|
meta = (class << klass; self; end)
|
23
|
-
meta.class_eval definition
|
24
19
|
|
25
|
-
|
20
|
+
go = method_introspection_data method
|
21
|
+
return attach_and_define_method method, go, meta
|
26
22
|
end
|
27
23
|
|
28
24
|
def setup_instance_method method
|
29
|
-
|
25
|
+
go = instance_method_introspection_data method
|
26
|
+
result = attach_and_define_method method, go, build_class
|
30
27
|
|
31
|
-
|
28
|
+
unless result
|
32
29
|
if parent
|
33
30
|
return superclass.gir_ffi_builder.setup_instance_method method
|
34
31
|
else
|
@@ -36,10 +33,6 @@ module GirFFI
|
|
36
33
|
end
|
37
34
|
end
|
38
35
|
|
39
|
-
klass = build_class
|
40
|
-
klass.class_eval "undef #{method}"
|
41
|
-
klass.class_eval definition
|
42
|
-
|
43
36
|
true
|
44
37
|
end
|
45
38
|
|
@@ -47,6 +40,13 @@ module GirFFI
|
|
47
40
|
info.signals.each do |s|
|
48
41
|
return s if s.name == signal_name
|
49
42
|
end
|
43
|
+
if info.type == :object
|
44
|
+
info.interfaces.each do |i|
|
45
|
+
i.signals.each do |s|
|
46
|
+
return s if s.name == signal_name
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
50
|
if info.parent
|
51
51
|
return superclass.gir_ffi_builder.find_signal signal_name
|
52
52
|
end
|
@@ -58,16 +58,11 @@ module GirFFI
|
|
58
58
|
unless defined? @klass
|
59
59
|
case info.type
|
60
60
|
when :object, :struct
|
61
|
-
|
62
|
-
setup_class unless already_set_up
|
61
|
+
instantiate_struct_class
|
63
62
|
when :union
|
64
63
|
instantiate_union_class
|
65
|
-
setup_class unless already_set_up
|
66
64
|
when :enum, :flags
|
67
|
-
|
68
|
-
vals = info.values.map {|v| [v.name.to_sym, v.value]}.flatten
|
69
|
-
lib.enum(@classname.to_sym, vals)
|
70
|
-
end
|
65
|
+
instantiate_enum_class
|
71
66
|
else
|
72
67
|
raise NotImplementedError, "Cannot build classes of type #{info.type}"
|
73
68
|
end
|
@@ -109,20 +104,29 @@ module GirFFI
|
|
109
104
|
@lib ||= namespace_module.const_get :Lib
|
110
105
|
end
|
111
106
|
|
112
|
-
def
|
107
|
+
def instantiate_struct_class
|
113
108
|
@klass = get_or_define_class namespace_module, @classname, superclass
|
114
109
|
@structklass = get_or_define_class @klass, :Struct, FFI::Struct
|
110
|
+
setup_class unless already_set_up
|
115
111
|
end
|
116
112
|
|
117
113
|
def instantiate_union_class
|
118
114
|
@klass = get_or_define_class namespace_module, @classname, superclass
|
119
115
|
@structklass = get_or_define_class @klass, :Struct, FFI::Union
|
116
|
+
setup_class unless already_set_up
|
117
|
+
end
|
118
|
+
|
119
|
+
def instantiate_enum_class
|
120
|
+
@klass = optionally_define_constant namespace_module, @classname do
|
121
|
+
vals = info.values.map {|v| [v.name.to_sym, v.value]}.flatten
|
122
|
+
lib.enum(@classname.to_sym, vals)
|
123
|
+
end
|
120
124
|
end
|
121
125
|
|
122
126
|
def setup_class
|
123
127
|
setup_layout
|
124
128
|
setup_constants
|
125
|
-
|
129
|
+
stub_methods
|
126
130
|
setup_gtype_getter
|
127
131
|
|
128
132
|
setup_vfunc_invokers if info.type == :object
|
@@ -140,6 +144,8 @@ module GirFFI
|
|
140
144
|
if fields.empty?
|
141
145
|
if parent
|
142
146
|
return [:parent, superclass.const_get(:Struct), 0]
|
147
|
+
else
|
148
|
+
return [:dummy, :char, 0]
|
143
149
|
end
|
144
150
|
end
|
145
151
|
|
@@ -161,20 +167,24 @@ module GirFFI
|
|
161
167
|
ffitype
|
162
168
|
end
|
163
169
|
|
164
|
-
def
|
170
|
+
def stub_methods
|
165
171
|
info.methods.each do |m|
|
166
|
-
@klass.class_eval "
|
167
|
-
def #{m.name} *args, &block
|
168
|
-
method_missing :#{m.name}, *args, &block
|
169
|
-
end
|
170
|
-
"
|
172
|
+
@klass.class_eval method_stub(m.method? ? m.name : "self.#{m.name}", m.name)
|
171
173
|
end
|
172
174
|
end
|
173
175
|
|
176
|
+
def method_stub name, symbol
|
177
|
+
"
|
178
|
+
def #{name} *args, &block
|
179
|
+
setup_and_call :#{symbol}, *args, &block
|
180
|
+
end
|
181
|
+
"
|
182
|
+
end
|
183
|
+
|
174
184
|
def setup_gtype_getter
|
175
185
|
getter = info.type_init
|
176
186
|
return if getter.nil? or getter == "intern"
|
177
|
-
lib.attach_function getter.to_sym, [], :
|
187
|
+
lib.attach_function getter.to_sym, [], :size_t
|
178
188
|
@klass.class_eval "
|
179
189
|
def self.get_gtype
|
180
190
|
::#{lib}.#{getter}
|
@@ -200,7 +210,7 @@ module GirFFI
|
|
200
210
|
return if info.find_method 'new'
|
201
211
|
|
202
212
|
(class << @klass; self; end).class_eval {
|
203
|
-
alias_method :new, :
|
213
|
+
alias_method :new, :allocate
|
204
214
|
}
|
205
215
|
end
|
206
216
|
|
@@ -217,17 +227,21 @@ module GirFFI
|
|
217
227
|
info.find_method method
|
218
228
|
end
|
219
229
|
|
230
|
+
def instance_method_introspection_data method
|
231
|
+
m = method_introspection_data method
|
232
|
+
return !m.nil? && m.method? ? m : nil
|
233
|
+
end
|
234
|
+
|
220
235
|
def function_definition go
|
221
236
|
FunctionDefinitionBuilder.new(go, lib).generate
|
222
237
|
end
|
223
238
|
|
224
|
-
def
|
225
|
-
|
226
|
-
|
227
|
-
return nil if go.nil?
|
228
|
-
|
239
|
+
def attach_and_define_method method, go, modul
|
240
|
+
return false if go.nil?
|
229
241
|
Builder.attach_ffi_function lib, go
|
230
|
-
|
242
|
+
modul.class_eval { remove_method method }
|
243
|
+
modul.class_eval function_definition(go)
|
244
|
+
true
|
231
245
|
end
|
232
246
|
|
233
247
|
def gir
|