gir_ffi 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -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