gir_ffi 0.0.6 → 0.0.7

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.
@@ -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
+