gir_ffi 0.0.7 → 0.0.8

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.
@@ -0,0 +1,27 @@
1
+ require 'gir_ffi/builder/type/base'
2
+ module GirFFI
3
+ module Builder
4
+ module Type
5
+
6
+ # Implements the creation of an enum or flags type. The type will be
7
+ # attached to the appropriate namespace module, and will be defined
8
+ # as an enum for FFI.
9
+ class Enum < Base
10
+ def build_class
11
+ unless defined? @klass
12
+ instantiate_enum_class
13
+ end
14
+ @klass
15
+ end
16
+
17
+ def instantiate_enum_class
18
+ @klass = optionally_define_constant namespace_module, @classname do
19
+ vals = info.values.map {|vinfo| [vinfo.name.to_sym, vinfo.value]}.flatten
20
+ lib.enum(@classname.to_sym, vals)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+
@@ -0,0 +1,12 @@
1
+ require 'gir_ffi/builder/type/struct_based'
2
+ module GirFFI
3
+ module Builder
4
+ module Type
5
+
6
+ # Implements the creation of a class representing an Interface.
7
+ class Interface < StructBased
8
+ end
9
+ end
10
+ end
11
+ end
12
+
@@ -0,0 +1,46 @@
1
+ require 'gir_ffi/builder/type/struct_based'
2
+ module GirFFI
3
+ module Builder
4
+ module Type
5
+
6
+ # Implements the creation of a class representing a GObject Object.
7
+ class Object < StructBased
8
+ def setup_class
9
+ super
10
+ setup_vfunc_invokers
11
+ end
12
+
13
+ def parent
14
+ unless defined? @parent
15
+ pr = info.parent
16
+ if pr.nil? or (pr.name == @classname and pr.namespace == @namespace)
17
+ @parent = nil
18
+ else
19
+ @parent = pr
20
+ end
21
+ end
22
+ @parent
23
+ end
24
+
25
+ def setup_vfunc_invokers
26
+ info.vfuncs.each do |vfinfo|
27
+ invoker = vfinfo.invoker
28
+ next if invoker.nil?
29
+ next if invoker.name == vfinfo.name
30
+
31
+ @klass.class_eval "
32
+ def #{vfinfo.name} *args, &block
33
+ #{invoker.name}(*args, &block)
34
+ end
35
+ "
36
+ end
37
+ end
38
+
39
+ def signal_definers
40
+ [info] + info.interfaces
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+
@@ -0,0 +1,156 @@
1
+ require 'gir_ffi/builder/type/base'
2
+ module GirFFI
3
+ module Builder
4
+ module Type
5
+
6
+ # Base class for type builders building types specified by subtypes
7
+ # of IRegisteredTypeInfo. These are types whose C representation is
8
+ # complex, i.e., a struct or a union.
9
+ class RegisteredType < Base
10
+ def setup_method method
11
+ klass = build_class
12
+ meta = (class << klass; self; end)
13
+
14
+ go = method_introspection_data method
15
+ raise NoMethodError unless go
16
+ attach_and_define_method method, go, meta
17
+ end
18
+
19
+ def setup_instance_method method
20
+ go = instance_method_introspection_data method
21
+ result = attach_and_define_method method, go, build_class
22
+
23
+ unless result
24
+ if parent
25
+ return superclass.gir_ffi_builder.setup_instance_method method
26
+ else
27
+ return false
28
+ end
29
+ end
30
+
31
+ true
32
+ end
33
+
34
+ private
35
+
36
+ def method_introspection_data method
37
+ info.find_method method
38
+ end
39
+
40
+ def instance_method_introspection_data method
41
+ data = method_introspection_data method
42
+ return !data.nil? && data.method? ? data : nil
43
+ end
44
+
45
+ def function_definition go
46
+ Builder::Function.new(go, lib).generate
47
+ end
48
+
49
+ def attach_and_define_method method, go, modul
50
+ return false if go.nil?
51
+ Builder.attach_ffi_function lib, go
52
+ modul.class_eval { remove_method method }
53
+ modul.class_eval function_definition(go)
54
+ true
55
+ end
56
+
57
+ def setup_class
58
+ setup_layout
59
+ setup_constants
60
+ stub_methods
61
+ setup_gtype_getter
62
+ end
63
+
64
+ def setup_layout
65
+ spec = layout_specification
66
+ @structklass.class_eval { layout(*spec) }
67
+ end
68
+
69
+ def layout_specification
70
+ fields = if info.info_type == :interface
71
+ []
72
+ else
73
+ info.fields
74
+ end
75
+
76
+ if fields.empty?
77
+ if parent
78
+ return [:parent, superclass.const_get(:Struct), 0]
79
+ else
80
+ return [:dummy, :char, 0]
81
+ end
82
+ end
83
+
84
+ fields.map do |finfo|
85
+ [ finfo.name.to_sym,
86
+ itypeinfo_to_ffitype_for_struct(finfo.field_type),
87
+ finfo.offset ]
88
+ end.flatten
89
+ end
90
+
91
+ def itypeinfo_to_ffitype_for_struct typeinfo
92
+ ffitype = Builder.itypeinfo_to_ffitype typeinfo
93
+ if ffitype.kind_of?(Class) and const_defined_for ffitype, :Struct
94
+ ffitype = ffitype.const_get :Struct
95
+ end
96
+ if ffitype == :bool
97
+ ffitype = :int
98
+ end
99
+ ffitype
100
+ end
101
+
102
+ def setup_constants
103
+ @klass.const_set :GIR_INFO, info
104
+ @klass.const_set :GIR_FFI_BUILDER, self
105
+ end
106
+
107
+ def already_set_up
108
+ const_defined_for @klass, :GIR_FFI_BUILDER
109
+ end
110
+
111
+ def stub_methods
112
+ info.get_methods.each do |minfo|
113
+ @klass.class_eval method_stub(minfo.name, minfo.method?)
114
+ end
115
+ end
116
+
117
+ def method_stub symbol, is_instance_method
118
+ "
119
+ def #{is_instance_method ? '' : 'self.'}#{symbol} *args, &block
120
+ setup_and_call :#{symbol}, *args, &block
121
+ end
122
+ "
123
+ end
124
+
125
+ def setup_gtype_getter
126
+ getter = info.type_init
127
+ return if getter.nil? or getter == "intern"
128
+ lib.attach_function getter.to_sym, [], :size_t
129
+ @klass.class_eval "
130
+ def self.get_gtype
131
+ ::#{lib}.#{getter}
132
+ end
133
+ "
134
+ end
135
+
136
+ def parent
137
+ nil
138
+ end
139
+
140
+ def superclass
141
+ unless defined? @superclass
142
+ if parent
143
+ @superclass = Builder.build_class parent
144
+ else
145
+ @superclass = GirFFI::ClassBase
146
+ end
147
+ end
148
+ @superclass
149
+ end
150
+ end
151
+ end
152
+ end
153
+ end
154
+
155
+
156
+
@@ -0,0 +1,25 @@
1
+ require 'gir_ffi/builder/type/struct_based'
2
+ module GirFFI
3
+ module Builder
4
+ module Type
5
+
6
+ # Implements the creation of a class representing a Struct.
7
+ class Struct < StructBased
8
+ def setup_class
9
+ super
10
+ provide_struct_constructor
11
+ end
12
+
13
+ def provide_struct_constructor
14
+ return if info.find_method 'new'
15
+
16
+ (class << @klass; self; end).class_eval {
17
+ alias_method :new, :allocate
18
+ }
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+
@@ -0,0 +1,40 @@
1
+ require 'gir_ffi/builder/type/registered_type'
2
+ module GirFFI
3
+ module Builder
4
+ module Type
5
+
6
+ # Implements the creation of a class representing one of the types
7
+ # whose C representation is a struct, i.e., :object, :struct, and
8
+ # :interface.
9
+ class StructBased < RegisteredType
10
+ def build_class
11
+ unless defined? @klass
12
+ instantiate_struct_class
13
+ end
14
+ @klass
15
+ end
16
+
17
+ def instantiate_struct_class
18
+ @klass = get_or_define_class namespace_module, @classname, superclass
19
+ @structklass = get_or_define_class @klass, :Struct, FFI::Struct
20
+ setup_class unless already_set_up
21
+ end
22
+
23
+ def find_signal signal_name
24
+ signal_definers.each do |inf|
25
+ inf.signals.each do |sig|
26
+ return sig if sig.name == signal_name
27
+ end
28
+ end
29
+ if parent
30
+ return superclass.gir_ffi_builder.find_signal signal_name
31
+ end
32
+ end
33
+
34
+ def signal_definers
35
+ [info]
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,26 @@
1
+ require 'gir_ffi/builder/type/registered_type'
2
+ module GirFFI
3
+ module Builder
4
+ module Type
5
+
6
+ # Implements the creation of a class representing union type. The
7
+ # class will have a nested FFI::Union class to represent its C union.
8
+ class Union < RegisteredType
9
+ def build_class
10
+ unless defined? @klass
11
+ instantiate_union_class
12
+ end
13
+ @klass
14
+ end
15
+
16
+ def instantiate_union_class
17
+ @klass = get_or_define_class namespace_module, @classname, superclass
18
+ @structklass = get_or_define_class @klass, :Struct, FFI::Union
19
+ setup_class unless already_set_up
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+
@@ -0,0 +1,33 @@
1
+ require 'gir_ffi/builder_helper'
2
+ require 'gir_ffi/builder/type/base'
3
+ require 'gir_ffi/builder/type/callback'
4
+ require 'gir_ffi/builder/type/enum'
5
+ require 'gir_ffi/builder/type/union'
6
+ require 'gir_ffi/builder/type/object'
7
+ require 'gir_ffi/builder/type/struct'
8
+ require 'gir_ffi/builder/type/interface'
9
+
10
+ module GirFFI
11
+ # Builds a class based on information found in the introspection
12
+ # repository.
13
+ module Builder
14
+ module Type
15
+ def self.build info
16
+ case info.info_type
17
+ when :callback
18
+ Callback
19
+ when :enum, :flags
20
+ Enum
21
+ when :union
22
+ Union
23
+ when :object
24
+ Object
25
+ when :struct
26
+ Struct
27
+ when :interface
28
+ Interface
29
+ end.new(info).build_class
30
+ end
31
+ end
32
+ end
33
+ end
@@ -1,7 +1,7 @@
1
1
  require 'gir_ffi/arg_helper'
2
2
  require 'gir_ffi/builder/function'
3
3
  require 'gir_ffi/class_base'
4
- require 'gir_ffi/builder/class'
4
+ require 'gir_ffi/builder/type'
5
5
  require 'gir_ffi/builder/module'
6
6
  require 'gir_ffi/builder_helper'
7
7
 
@@ -10,14 +10,10 @@ 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
-
15
13
  extend BuilderHelper
16
14
 
17
15
  TAG_TYPE_MAP = {
18
- :boolean => :bool,
19
16
  :GType => :size_t,
20
- :size => :size_t,
21
17
  :gboolean => :bool,
22
18
  :gint8 => :int8,
23
19
  :guint8 => :uint8,
@@ -29,14 +25,15 @@ module GirFFI
29
25
  :guint64 => :uint64,
30
26
  :gfloat => :float,
31
27
  :gdouble => :double,
28
+ :void => :void
32
29
  }
33
30
 
34
31
  def self.build_class info
35
- Builder::Class.new(info).generate
32
+ Builder::Type.build(info)
36
33
  end
37
34
 
38
- def self.build_module namespace
39
- Builder::Module.new(namespace).generate
35
+ def self.build_module namespace, version=nil
36
+ Builder::Module.new(namespace, version).generate
40
37
  end
41
38
 
42
39
  def self.attach_ffi_function lib, info
@@ -48,61 +45,36 @@ module GirFFI
48
45
  end
49
46
 
50
47
  def self.ffi_function_argument_types info
51
- types = info.args.map do |arg|
52
- tp = iarginfo_to_ffitype arg
53
- tp == :string ? :pointer : tp
54
- end
55
- if info.type == :function
48
+ types = info.args.map { |arg| iarginfo_to_ffitype arg }
49
+
50
+ if info.info_type == :function
56
51
  types.unshift :pointer if info.method?
57
52
  types << :pointer if info.throws?
58
53
  end
54
+
59
55
  types
60
56
  end
61
57
 
62
58
  def self.ffi_function_return_type info
63
- itypeinfo_to_ffitype info.return_type
59
+ rt = info.return_type
60
+ return :string if rt.tag == :utf8
61
+ itypeinfo_to_ffitype rt
64
62
  end
65
63
 
66
64
  def self.itypeinfo_to_ffitype info
67
- tag = info.tag
68
-
69
- if info.pointer?
70
- return :string if tag == :utf8
71
- return :pointer
72
- end
65
+ return :pointer if info.pointer?
73
66
 
74
- case tag
75
- when :interface
76
- interface = info.interface
77
- return build_class interface
78
- when :ssize
79
- return FFI_TYPE_FOR_SSIZE_T
67
+ tag = info.tag
68
+ if tag == :interface
69
+ return build_class info.interface
80
70
  else
81
- if TAG_TYPE_MAP[tag]
82
- return TAG_TYPE_MAP[tag]
83
- else
84
- return tag
85
- end
71
+ return TAG_TYPE_MAP[tag]
86
72
  end
87
73
  end
88
74
 
89
75
  def self.iarginfo_to_ffitype info
90
- return :pointer if info.direction == :inout
91
- return :pointer if info.direction == :out
92
- return itypeinfo_to_ffitype info.type
93
- end
94
-
95
- def self.build_callback interface
96
- modul = build_module interface.namespace
97
- lib = modul.const_get(:Lib)
98
-
99
- sym = interface.name.to_sym
100
-
101
- optionally_define_constant modul, sym do
102
- args = ffi_function_argument_types interface
103
- ret = ffi_function_return_type interface
104
- lib.callback sym, args, ret
105
- end
76
+ return :pointer if info.direction != :in
77
+ return itypeinfo_to_ffitype info.argument_type
106
78
  end
107
79
  end
108
80
  end
@@ -6,32 +6,42 @@ module GirFFI
6
6
  def direction
7
7
  Lib.g_arg_info_get_direction @gobj
8
8
  end
9
+
9
10
  def return_value?
10
11
  Lib.g_arg_info_is_return_value @gobj
11
12
  end
13
+
12
14
  def optional?
13
15
  Lib.g_arg_info_is_optional @gobj
14
16
  end
17
+
15
18
  def caller_allocates?
16
19
  Lib.g_arg_info_is_caller_allocates @gobj
17
20
  end
21
+
18
22
  def may_be_null?
19
23
  Lib.g_arg_info_may_be_null @gobj
20
24
  end
25
+
21
26
  def ownership_transfer
22
27
  Lib.g_arg_info_get_ownership_transfer @gobj
23
28
  end
29
+
24
30
  def scope
25
31
  Lib.g_arg_info_get_scope @gobj
26
32
  end
33
+
27
34
  def closure
28
35
  Lib.g_arg_info_get_closure @gobj
29
36
  end
37
+
30
38
  def destroy
31
39
  Lib.g_arg_info_get_destroy @gobj
32
40
  end
33
- def type
41
+
42
+ def argument_type
34
43
  ITypeInfo.wrap(Lib.g_arg_info_get_type @gobj)
35
44
  end
36
45
  end
37
46
  end
47
+
@@ -19,8 +19,9 @@ module GirFFI
19
19
  # Provide the second parameter if the plural is not trivially
20
20
  # constructed by adding +s+ to the singular.
21
21
  def self.build_array_method method, single = nil
22
- single ||= method.to_s[0..-2]
23
- count = "n_#{method}"
22
+ method = method.to_s
23
+ single ||= method[0..-2]
24
+ count = method.sub(/^(get_)?/, "\\1n_")
24
25
  self.class_eval <<-CODE
25
26
  def #{method}
26
27
  (0..(#{count} - 1)).map do |i|
@@ -36,7 +37,7 @@ module GirFFI
36
37
  Lib.g_base_info_get_name @gobj
37
38
  end
38
39
 
39
- def type
40
+ def info_type
40
41
  Lib.g_base_info_get_type @gobj
41
42
  end
42
43
 
@@ -5,13 +5,16 @@ module GirFFI
5
5
  def flags
6
6
  Lib.g_field_info_get_flags @gobj
7
7
  end
8
+
8
9
  def size
9
10
  Lib.g_field_info_get_size @gobj
10
11
  end
12
+
11
13
  def offset
12
14
  Lib.g_field_info_get_offset @gobj
13
15
  end
14
- def type
16
+
17
+ def field_type
15
18
  ITypeInfo.wrap(Lib.g_field_info_get_type @gobj)
16
19
  end
17
20
  end
@@ -20,14 +20,14 @@ module GirFFI
20
20
  ##
21
21
  build_array_method :properties, :property
22
22
 
23
- def n_methods
23
+ def get_n_methods
24
24
  Lib.g_interface_info_get_n_methods @gobj
25
25
  end
26
- def method index
26
+ def get_method index
27
27
  IFunctionInfo.wrap(Lib.g_interface_info_get_method @gobj, index)
28
28
  end
29
29
  ##
30
- build_array_method :methods
30
+ build_array_method :get_methods
31
31
 
32
32
  def find_method name
33
33
  IFunctionInfo.wrap(Lib.g_interface_info_find_method @gobj, name)
@@ -42,14 +42,16 @@ module GirFFI
42
42
  ##
43
43
  build_array_method :properties, :property
44
44
 
45
- def n_methods
45
+ def get_n_methods
46
46
  Lib.g_object_info_get_n_methods @gobj
47
47
  end
48
- def method(index)
48
+
49
+ def get_method(index)
49
50
  IFunctionInfo.wrap(Lib.g_object_info_get_method @gobj, index)
50
51
  end
52
+
51
53
  ##
52
- build_array_method :methods
54
+ build_array_method :get_methods
53
55
 
54
56
  def find_method(name)
55
57
  IFunctionInfo.wrap(Lib.g_object_info_find_method @gobj, name)
@@ -12,23 +12,21 @@ module GirFFI
12
12
  ##
13
13
  build_array_method :fields
14
14
 
15
- def n_methods
15
+ def get_n_methods
16
16
  Lib.g_struct_info_get_n_methods @gobj
17
17
  end
18
- def method(index)
18
+ def get_method(index)
19
19
  IFunctionInfo.wrap(Lib.g_struct_info_get_method @gobj, index)
20
20
  end
21
21
 
22
22
  ##
23
- build_array_method :methods
24
-
25
- def methods_hash
26
- @methods_hash ||= methods.inject({}) {|h,m| h[m.name] = m; h}
27
- end
23
+ build_array_method :get_methods
28
24
 
29
25
  def find_method(name)
30
- methods_hash[name]
26
+ @methods_hash ||= get_methods.inject({}) {|h,m| h[m.name] = m; h}
27
+ @methods_hash[name]
31
28
  end
29
+
32
30
  def size
33
31
  Lib.g_struct_info_get_size @gobj
34
32
  end
@@ -9,11 +9,11 @@ module GirFFI
9
9
  ##
10
10
  build_array_method :fields
11
11
 
12
- def n_methods; Lib.g_union_info_get_n_methods @gobj; end
13
- def method(index); IFunctionInfo.wrap(Lib.g_union_info_get_method @gobj, index); end
12
+ def get_n_methods; Lib.g_union_info_get_n_methods @gobj; end
13
+ def get_method(index); IFunctionInfo.wrap(Lib.g_union_info_get_method @gobj, index); end
14
14
 
15
15
  ##
16
- build_array_method :methods
16
+ build_array_method :get_methods
17
17
 
18
18
  def find_method(name); IFunctionInfo.wrap(Lib.g_union_info_find_method @gobj, name); end
19
19
  def size; Lib.g_union_info_get_size @gobj; end
@@ -150,18 +150,18 @@ module GirFFI
150
150
  end
151
151
 
152
152
  def self.signal_argument_to_gvalue info, arg
153
- if info.type.tag == :interface
154
- interface = info.type.interface
153
+ if info.argument_type.tag == :interface
154
+ interface = info.argument_type.interface
155
155
 
156
156
  val = ::GObject::Value.new
157
- val.init info.type.interface.g_type
158
- case interface.type
157
+ val.init info.argument_type.interface.g_type
158
+ case interface.info_type
159
159
  when :struct
160
160
  val.set_boxed arg
161
161
  when :object
162
162
  val.set_instance arg
163
163
  else
164
- raise NotImplementedError, interface.type
164
+ raise NotImplementedError, interface.info_type
165
165
  end
166
166
 
167
167
  return val
@@ -198,8 +198,8 @@ module GirFFI
198
198
  # Extra arguments
199
199
  signalinfo.args.each do |info|
200
200
  arg = args.shift
201
- if info.type.tag == :interface
202
- iface = info.type.interface
201
+ if info.argument_type.tag == :interface
202
+ iface = info.argument_type.interface
203
203
  kls = GirFFI::Builder.build_class iface
204
204
  result << kls.wrap(arg)
205
205
  else