gir_ffi 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,11 +2,13 @@ require 'gir_ffi/builder_helper'
2
2
  module GirFFI
3
3
  # Builds a class based on information found in the introspection
4
4
  # repository.
5
- class ClassBuilder
5
+ class Builder::Class
6
6
  include BuilderHelper
7
- def initialize namespace, classname
8
- @namespace = namespace
9
- @classname = classname
7
+
8
+ def initialize info
9
+ @info = info
10
+ @namespace = @info.namespace
11
+ @classname = @info.name.gsub(/^(.)/) { $1.upcase }
10
12
  end
11
13
 
12
14
  def generate
@@ -18,7 +20,8 @@ module GirFFI
18
20
  meta = (class << klass; self; end)
19
21
 
20
22
  go = method_introspection_data method
21
- return attach_and_define_method method, go, meta
23
+ raise NoMethodError unless go
24
+ attach_and_define_method method, go, meta
22
25
  end
23
26
 
24
27
  def setup_instance_method method
@@ -26,11 +29,11 @@ module GirFFI
26
29
  result = attach_and_define_method method, go, build_class
27
30
 
28
31
  unless result
29
- if parent
30
- return superclass.gir_ffi_builder.setup_instance_method method
31
- else
32
- return false
33
- end
32
+ if parent
33
+ return superclass.gir_ffi_builder.setup_instance_method method
34
+ else
35
+ return false
36
+ end
34
37
  end
35
38
 
36
39
  true
@@ -42,8 +45,8 @@ module GirFFI
42
45
  return sig if sig.name == signal_name
43
46
  end
44
47
  end
45
- if info.parent
46
- return superclass.gir_ffi_builder.find_signal signal_name
48
+ if parent
49
+ return superclass.gir_ffi_builder.find_signal signal_name
47
50
  end
48
51
  end
49
52
 
@@ -51,42 +54,53 @@ module GirFFI
51
54
 
52
55
  def build_class
53
56
  unless defined? @klass
54
- case info.type
55
- when :object, :struct, :interface
56
- instantiate_struct_class
57
- when :union
58
- instantiate_union_class
59
- when :enum, :flags
60
- instantiate_enum_class
61
- else
62
- raise NotImplementedError, "Cannot build classes of type #{info.type}"
63
- end
57
+ case info.type
58
+ when :object, :struct, :interface
59
+ instantiate_struct_class
60
+ when :union
61
+ instantiate_union_class
62
+ when :enum, :flags
63
+ instantiate_enum_class
64
+ when :callback
65
+ instantiate_callback_class
66
+ else
67
+ raise NotImplementedError, "Cannot build classes of type #{info.type}"
68
+ end
64
69
  end
65
70
  @klass
66
71
  end
67
72
 
68
73
  def info
69
74
  unless defined? @info
70
- @info = gir.find_by_name @namespace, @classname
71
- raise "Class #{@classname} not found in namespace #{@namespace}" if @info.nil?
75
+ @info = gir.find_by_name @namespace, @classname
76
+ raise "Class #{@classname} not found in namespace #{@namespace}" if @info.nil?
72
77
  end
73
78
  @info
74
79
  end
75
80
 
76
81
  def parent
77
82
  unless defined? @parent
78
- @parent = info.type == :object ? info.parent : nil
83
+ if info.type == :object
84
+ pr = info.parent
85
+ if pr.nil? or (pr.name == @classname and pr.namespace == @namespace)
86
+ @parent = nil
87
+ else
88
+ @parent = pr
89
+ end
90
+ else
91
+ @parent = nil
92
+ end
79
93
  end
80
94
  @parent
81
95
  end
82
96
 
83
97
  def superclass
84
98
  unless defined? @superclass
85
- if parent
86
- @superclass = Builder.build_class parent.namespace, parent.name
87
- else
88
- @superclass = GirFFI::ClassBase
89
- end
99
+ if parent
100
+ @superclass = Builder.build_class parent
101
+ else
102
+ @superclass = GirFFI::ClassBase
103
+ end
90
104
  end
91
105
  @superclass
92
106
  end
@@ -113,8 +127,16 @@ module GirFFI
113
127
 
114
128
  def instantiate_enum_class
115
129
  @klass = optionally_define_constant namespace_module, @classname do
116
- vals = info.values.map {|vinfo| [vinfo.name.to_sym, vinfo.value]}.flatten
117
- lib.enum(@classname.to_sym, vals)
130
+ vals = info.values.map {|vinfo| [vinfo.name.to_sym, vinfo.value]}.flatten
131
+ lib.enum(@classname.to_sym, vals)
132
+ end
133
+ end
134
+
135
+ def instantiate_callback_class
136
+ @klass = optionally_define_constant namespace_module, @classname do
137
+ args = Builder.ffi_function_argument_types info
138
+ ret = Builder.ffi_function_return_type info
139
+ lib.callback @classname.to_sym, args, ret
118
140
  end
119
141
  end
120
142
 
@@ -135,48 +157,48 @@ module GirFFI
135
157
 
136
158
  def layout_specification
137
159
  fields = if info.type == :interface
138
- []
139
- else
140
- info.fields
141
- end
160
+ []
161
+ else
162
+ info.fields
163
+ end
142
164
 
143
165
  if fields.empty?
144
- if parent
145
- return [:parent, superclass.const_get(:Struct), 0]
146
- else
147
- return [:dummy, :char, 0]
148
- end
166
+ if parent
167
+ return [:parent, superclass.const_get(:Struct), 0]
168
+ else
169
+ return [:dummy, :char, 0]
170
+ end
149
171
  end
150
172
 
151
173
  fields.map do |finfo|
152
- [ finfo.name.to_sym,
153
- itypeinfo_to_ffitype_for_struct(finfo.type),
154
- finfo.offset ]
174
+ [ finfo.name.to_sym,
175
+ itypeinfo_to_ffitype_for_struct(finfo.type),
176
+ finfo.offset ]
155
177
  end.flatten
156
178
  end
157
179
 
158
180
  def itypeinfo_to_ffitype_for_struct typeinfo
159
181
  ffitype = Builder.itypeinfo_to_ffitype typeinfo
160
182
  if ffitype.kind_of?(Class) and const_defined_for ffitype, :Struct
161
- ffitype = ffitype.const_get :Struct
183
+ ffitype = ffitype.const_get :Struct
162
184
  end
163
185
  if ffitype == :bool
164
- ffitype = :int
186
+ ffitype = :int
165
187
  end
166
188
  ffitype
167
189
  end
168
190
 
169
191
  def stub_methods
170
192
  info.methods.each do |minfo|
171
- @klass.class_eval method_stub(minfo.name, minfo.method?)
193
+ @klass.class_eval method_stub(minfo.name, minfo.method?)
172
194
  end
173
195
  end
174
196
 
175
197
  def method_stub symbol, is_instance_method
176
198
  "
177
- def #{is_instance_method ? '' : 'self.'}#{symbol} *args, &block
178
- setup_and_call :#{symbol}, *args, &block
179
- end
199
+ def #{is_instance_method ? '' : 'self.'}#{symbol} *args, &block
200
+ setup_and_call :#{symbol}, *args, &block
201
+ end
180
202
  "
181
203
  end
182
204
 
@@ -185,23 +207,23 @@ module GirFFI
185
207
  return if getter.nil? or getter == "intern"
186
208
  lib.attach_function getter.to_sym, [], :size_t
187
209
  @klass.class_eval "
188
- def self.get_gtype
189
- ::#{lib}.#{getter}
190
- end
210
+ def self.get_gtype
211
+ ::#{lib}.#{getter}
212
+ end
191
213
  "
192
214
  end
193
215
 
194
216
  def setup_vfunc_invokers
195
217
  info.vfuncs.each do |vfinfo|
196
- invoker = vfinfo.invoker
197
- next if invoker.nil?
198
- next if invoker.name == vfinfo.name
199
-
200
- @klass.class_eval "
201
- def #{vfinfo.name} *args, &block
202
- #{invoker.name}(*args, &block)
203
- end
204
- "
218
+ invoker = vfinfo.invoker
219
+ next if invoker.nil?
220
+ next if invoker.name == vfinfo.name
221
+
222
+ @klass.class_eval "
223
+ def #{vfinfo.name} *args, &block
224
+ #{invoker.name}(*args, &block)
225
+ end
226
+ "
205
227
  end
206
228
  end
207
229
 
@@ -209,7 +231,7 @@ module GirFFI
209
231
  return if info.find_method 'new'
210
232
 
211
233
  (class << @klass; self; end).class_eval {
212
- alias_method :new, :allocate
234
+ alias_method :new, :allocate
213
235
  }
214
236
  end
215
237
 
@@ -232,7 +254,7 @@ module GirFFI
232
254
  end
233
255
 
234
256
  def function_definition go
235
- FunctionDefinitionBuilder.new(go, lib).generate
257
+ Builder::Function.new(go, lib).generate
236
258
  end
237
259
 
238
260
  def attach_and_define_method method, go, modul
@@ -245,15 +267,15 @@ module GirFFI
245
267
 
246
268
  def gir
247
269
  unless defined? @gir
248
- @gir = IRepository.default
249
- @gir.require @namespace, nil
270
+ @gir = IRepository.default
271
+ @gir.require @namespace, nil
250
272
  end
251
273
  @gir
252
274
  end
253
275
 
254
276
  def get_or_define_class namespace, name, parent
255
277
  optionally_define_constant(namespace, name) {
256
- Class.new parent
278
+ Class.new parent
257
279
  }
258
280
  end
259
281
 
@@ -1,9 +1,9 @@
1
- require 'gir_ffi/argument_builder'
1
+ require 'gir_ffi/builder/argument'
2
2
 
3
- module GirFFI
3
+ module GirFFI::Builder
4
4
  # Implements the creation of a Ruby function definition out of a GIR
5
5
  # IFunctionInfo.
6
- class FunctionDefinitionBuilder
6
+ class Function
7
7
  def initialize info, libmodule
8
8
  @info = info
9
9
  @libmodule = libmodule
@@ -11,19 +11,20 @@ module GirFFI
11
11
 
12
12
  def generate
13
13
  setup_accumulators
14
- @data = @info.args.map {|arg| ArgumentBuilder.build self, arg, @libmodule}
15
- @rvdata = ReturnValueBuilder.new self, @info
14
+ @data = @info.args.map {|arg| Argument.build self, arg, @libmodule}
15
+ @rvdata = ReturnValue.build self, @info
16
16
 
17
17
  alldata = @data.dup << @rvdata
18
18
 
19
19
  alldata.each {|data|
20
20
  data.prepare
21
21
  idx = data.type.array_length
22
- data.length_arg = @data[idx] if idx > -1
22
+ if idx > -1
23
+ data.length_arg = @data[idx]
24
+ @data[idx].length_arg_for = data
25
+ end
23
26
  }
24
27
 
25
- alldata.each {|data| data.process }
26
-
27
28
  adjust_accumulators
28
29
  return filled_out_template
29
30
  end
@@ -35,10 +36,9 @@ module GirFFI
35
36
  end
36
37
 
37
38
  def adjust_accumulators
38
- klass = @info.throws? ? ErrorHandlerBuilder : NullArgumentBuilder
39
+ klass = @info.throws? ? ErrorArgument : NullArgument
39
40
  @errarg = klass.new(self)
40
41
  @errarg.prepare
41
- @errarg.process
42
42
  end
43
43
 
44
44
  def filled_out_template
@@ -4,7 +4,7 @@ require 'gir_ffi/module_base'
4
4
  module GirFFI
5
5
  # Builds a module based on information found in the introspection
6
6
  # repository.
7
- class ModuleBuilder
7
+ class Builder::Module
8
8
  include BuilderHelper
9
9
 
10
10
  def initialize namespace
@@ -32,16 +32,17 @@ module GirFFI
32
32
  end
33
33
 
34
34
  def build_class classname
35
- Builder.build_class @namespace, classname.to_s
35
+ info = gir.find_by_name @namespace, classname.to_s
36
+ Builder.build_class info
36
37
  end
37
38
 
38
39
  private
39
40
 
40
41
  def build_module
41
42
  unless defined? @module
42
- instantiate_module
43
- setup_lib_for_ffi
44
- setup_module unless already_set_up
43
+ instantiate_module
44
+ setup_lib_for_ffi
45
+ setup_module unless already_set_up
45
46
  end
46
47
  @module
47
48
  end
@@ -54,8 +55,8 @@ module GirFFI
54
55
  @module.extend ModuleBase
55
56
  @module.const_set :GIR_FFI_BUILDER, self
56
57
  begin
57
- require "gir_ffi/overrides/#{@namespace.downcase}"
58
- @module.class_eval "include GirFFI::Overrides::#{@namespace}"
58
+ require "gir_ffi/overrides/#{@namespace.downcase}"
59
+ @module.class_eval "include GirFFI::Overrides::#{@namespace}"
59
60
  rescue LoadError
60
61
  end
61
62
  end
@@ -68,10 +69,10 @@ module GirFFI
68
69
  @lib = get_or_define_module @module, :Lib
69
70
 
70
71
  unless (class << @lib; self.include? FFI::Library; end)
71
- @lib.extend FFI::Library
72
- libs = gir.shared_library(@namespace).split(/,/)
73
- @lib.ffi_lib_flags :global, :lazy
74
- @lib.ffi_lib(*libs)
72
+ @lib.extend FFI::Library
73
+ libs = gir.shared_library(@namespace).split(/,/)
74
+ @lib.ffi_lib_flags :global, :lazy
75
+ @lib.ffi_lib(*libs)
75
76
  end
76
77
 
77
78
  optionally_define_constant(@lib, :CALLBACKS) { [] }
@@ -81,20 +82,20 @@ module GirFFI
81
82
  info = gir.find_by_name @namespace, function.to_s
82
83
 
83
84
  if info.type == :function
84
- info
85
+ info
85
86
  else
86
- nil
87
+ nil
87
88
  end
88
89
  end
89
90
 
90
91
  def function_definition info, libmodule
91
- FunctionDefinitionBuilder.new(info, libmodule).generate
92
+ Builder::Function.new(info, libmodule).generate
92
93
  end
93
94
 
94
95
  def gir
95
96
  unless defined? @gir
96
- @gir = IRepository.default
97
- @gir.require @namespace, nil
97
+ @gir = IRepository.default
98
+ @gir.require @namespace, nil
98
99
  end
99
100
  @gir
100
101
  end
@@ -1,8 +1,8 @@
1
1
  require 'gir_ffi/arg_helper'
2
- require 'gir_ffi/function_definition_builder'
2
+ require 'gir_ffi/builder/function'
3
3
  require 'gir_ffi/class_base'
4
- require 'gir_ffi/class_builder'
5
- require 'gir_ffi/module_builder'
4
+ require 'gir_ffi/builder/class'
5
+ require 'gir_ffi/builder/module'
6
6
  require 'gir_ffi/builder_helper'
7
7
 
8
8
  module GirFFI
@@ -10,13 +10,33 @@ module GirFFI
10
10
  # introspection repository. Call its build_module and build_class methods
11
11
  # to create the modules and classes used in your program.
12
12
  module Builder
13
+ FFI_TYPE_FOR_SSIZE_T = "int#{FFI.type_size(:size_t) * 8}".to_sym
14
+
13
15
  extend BuilderHelper
14
- def self.build_class namespace, classname
15
- ClassBuilder.new(namespace, classname).generate
16
+
17
+ TAG_TYPE_MAP = {
18
+ :boolean => :bool,
19
+ :GType => :size_t,
20
+ :size => :size_t,
21
+ :gboolean => :bool,
22
+ :gint8 => :int8,
23
+ :guint8 => :uint8,
24
+ :gint16 => :int16,
25
+ :guint16 => :uint16,
26
+ :gint32 => :int32,
27
+ :guint32 => :uint32,
28
+ :gint64 => :int64,
29
+ :guint64 => :uint64,
30
+ :gfloat => :float,
31
+ :gdouble => :double,
32
+ }
33
+
34
+ def self.build_class info
35
+ Builder::Class.new(info).generate
16
36
  end
17
37
 
18
38
  def self.build_module namespace
19
- ModuleBuilder.new(namespace).generate
39
+ Builder::Module.new(namespace).generate
20
40
  end
21
41
 
22
42
  def self.attach_ffi_function lib, info
@@ -27,8 +47,6 @@ module GirFFI
27
47
  lib.attach_function sym, argtypes, rt
28
48
  end
29
49
 
30
- # All methods below will be made private at the end.
31
-
32
50
  def self.ffi_function_argument_types info
33
51
  types = info.args.map do |arg|
34
52
  tp = iarginfo_to_ffitype arg
@@ -56,20 +74,15 @@ module GirFFI
56
74
  case tag
57
75
  when :interface
58
76
  interface = info.interface
59
- case interface.type
60
- when :object, :struct, :flags, :enum
61
- return build_class interface.namespace, interface.name
62
- when :callback
63
- return build_callback interface
77
+ return build_class interface
78
+ when :ssize
79
+ return FFI_TYPE_FOR_SSIZE_T
80
+ else
81
+ if TAG_TYPE_MAP[tag]
82
+ return TAG_TYPE_MAP[tag]
64
83
  else
65
- raise NotImplementedError
84
+ return tag
66
85
  end
67
- when :boolean
68
- return :bool
69
- when :GType, :size
70
- return :size_t
71
- else
72
- return tag
73
86
  end
74
87
  end
75
88
 
@@ -91,13 +104,5 @@ module GirFFI
91
104
  lib.callback sym, args, ret
92
105
  end
93
106
  end
94
-
95
- # Set up method access.
96
- (self.public_methods - Module.public_methods).each do |method|
97
- private_class_method method.to_sym
98
- end
99
- public_class_method :build_module, :build_class
100
- public_class_method :itypeinfo_to_ffitype
101
- public_class_method :attach_ffi_function
102
107
  end
103
108
  end
@@ -3,6 +3,7 @@ module GirFFI
3
3
  # Base class for all generated classes. Contains code for dealing with
4
4
  # the generated Struct classes.
5
5
  class ClassBase
6
+ # TODO: Make separate base for :struct, :union, :object.
6
7
  extend Forwardable
7
8
  def_delegators :@struct, :[], :[]=, :to_ptr
8
9
 
@@ -25,8 +26,7 @@ module GirFFI
25
26
  end
26
27
 
27
28
  def self.setup_and_call method, *arguments, &block
28
- result = gir_ffi_builder.setup_method method.to_s
29
- return super unless result
29
+ gir_ffi_builder.setup_method method.to_s
30
30
  self.send method, *arguments, &block
31
31
  end
32
32
 
@@ -51,6 +51,11 @@ module GirFFI
51
51
  _real_new ptr
52
52
  end
53
53
 
54
+ # TODO: Only makes sense for :objects.
55
+ def constructor_wrap ptr
56
+ wrap ptr
57
+ end
58
+
54
59
  def allocate
55
60
  _real_new
56
61
  end
@@ -35,12 +35,20 @@ module GirFFI
35
35
  def name
36
36
  Lib.g_base_info_get_name @gobj
37
37
  end
38
+
38
39
  def type
39
40
  Lib.g_base_info_get_type @gobj
40
41
  end
42
+
41
43
  def namespace
42
44
  Lib.g_base_info_get_namespace @gobj
43
45
  end
46
+
47
+ def container
48
+ ptr = Lib.g_base_info_get_container @gobj
49
+ IRepository.wrap_ibaseinfo_pointer ptr
50
+ end
51
+
44
52
  def deprecated?
45
53
  Lib.g_base_info_is_deprecated @gobj
46
54
  end
@@ -62,6 +62,12 @@ module GirFFI
62
62
  self.instance
63
63
  end
64
64
 
65
+ # TODO: Make sure GType is initialized first.
66
+ def self.prepend_search_path path
67
+ Lib.g_irepository_prepend_search_path path
68
+ end
69
+
70
+ # TODO: Make sure GType is initialized first.
65
71
  def self.type_tag_to_string type
66
72
  Lib.g_type_tag_to_string type
67
73
  end
@@ -22,8 +22,12 @@ module GirFFI
22
22
  ##
23
23
  build_array_method :methods
24
24
 
25
+ def methods_hash
26
+ @methods_hash ||= methods.inject({}) {|h,m| h[m.name] = m; h}
27
+ end
28
+
25
29
  def find_method(name)
26
- IFunctionInfo.wrap(Lib.g_struct_info_find_method @gobj, name)
30
+ methods_hash[name]
27
31
  end
28
32
  def size
29
33
  Lib.g_struct_info_get_size @gobj
data/lib/gir_ffi/lib.rb CHANGED
@@ -9,6 +9,7 @@ module GirFFI
9
9
  enum :IRepositoryLoadFlags, [:LAZY, (1<<0)]
10
10
 
11
11
  attach_function :g_irepository_get_default, [], :pointer
12
+ attach_function :g_irepository_prepend_search_path, [:string], :void
12
13
  attach_function :g_irepository_require,
13
14
  [:pointer, :string, :string, :IRepositoryLoadFlags, :pointer],
14
15
  :pointer
@@ -49,6 +50,7 @@ module GirFFI
49
50
  attach_function :g_base_info_get_type, [:pointer], :IInfoType
50
51
  attach_function :g_base_info_get_name, [:pointer], :string
51
52
  attach_function :g_base_info_get_namespace, [:pointer], :string
53
+ attach_function :g_base_info_get_container, [:pointer], :pointer
52
54
  attach_function :g_base_info_is_deprecated, [:pointer], :bool
53
55
  attach_function :g_base_info_equal, [:pointer, :pointer], :bool
54
56
 
@@ -0,0 +1,30 @@
1
+ module GirFFI
2
+ module Overrides
3
+ module GLib
4
+ def self.included base
5
+ base.extend ClassMethods
6
+ attach_non_introspectable_functions(base)
7
+ end
8
+
9
+ def self.attach_non_introspectable_functions base
10
+ base::Lib.attach_function :g_slist_prepend, [:pointer, :pointer],
11
+ :pointer
12
+ base::Lib.attach_function :g_list_append, [:pointer, :pointer],
13
+ :pointer
14
+ end
15
+
16
+ module ClassMethods
17
+ # FIXME: Should not be so visible for end users.
18
+ def slist_prepend slist, data
19
+ ::GLib::SList.wrap(::GLib::Lib.g_slist_prepend slist, data)
20
+ end
21
+
22
+ # FIXME: Should not be so visible for end users.
23
+ def list_append list, data
24
+ ::GLib::List.wrap(::GLib::Lib.g_list_append list, data)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+