gir_ffi 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. data/History.txt +14 -0
  2. data/TODO.rdoc +10 -5
  3. data/lib/ffi-glib.rb +7 -73
  4. data/lib/ffi-glib/array.rb +29 -4
  5. data/lib/ffi-glib/byte_array.rb +15 -1
  6. data/lib/ffi-glib/hash_table.rb +31 -24
  7. data/lib/ffi-glib/list.rb +28 -0
  8. data/lib/ffi-glib/list_methods.rb +10 -2
  9. data/lib/ffi-glib/ptr_array.rb +39 -0
  10. data/lib/ffi-glib/s_list.rb +29 -0
  11. data/lib/ffi-gobject.rb +49 -22
  12. data/lib/ffi-gobject/closure.rb +4 -3
  13. data/lib/ffi-gobject/helper.rb +20 -43
  14. data/lib/ffi-gobject/initially_unowned.rb +2 -0
  15. data/lib/ffi-gobject/object.rb +54 -0
  16. data/lib/ffi-gobject/ruby_closure.rb +22 -16
  17. data/lib/ffi-gobject/value.rb +54 -19
  18. data/lib/ffi-gobject_introspection/i_constant_info.rb +17 -1
  19. data/lib/ffi-gobject_introspection/i_field_info.rb +8 -0
  20. data/lib/ffi-gobject_introspection/i_property_info.rb +3 -1
  21. data/lib/ffi-gobject_introspection/lib.rb +19 -2
  22. data/lib/gir_ffi/arg_helper.rb +7 -45
  23. data/lib/gir_ffi/builder.rb +1 -1
  24. data/lib/gir_ffi/builder/argument.rb +148 -107
  25. data/lib/gir_ffi/builder/argument/base.rb +5 -5
  26. data/lib/gir_ffi/builder/argument/in_base.rb +2 -2
  27. data/lib/gir_ffi/builder/argument/in_out_base.rb +2 -3
  28. data/lib/gir_ffi/builder/argument/out_base.rb +2 -3
  29. data/lib/gir_ffi/builder/function.rb +11 -17
  30. data/lib/gir_ffi/builder/module.rb +26 -0
  31. data/lib/gir_ffi/builder/type.rb +5 -0
  32. data/lib/gir_ffi/builder/type/base.rb +2 -0
  33. data/lib/gir_ffi/builder/type/callback.rb +18 -3
  34. data/lib/gir_ffi/builder/type/constant.rb +4 -12
  35. data/lib/gir_ffi/builder/type/enum.rb +15 -6
  36. data/lib/gir_ffi/builder/type/interface.rb +4 -0
  37. data/lib/gir_ffi/builder/type/object.rb +11 -0
  38. data/lib/gir_ffi/builder/type/struct_based.rb +14 -4
  39. data/lib/gir_ffi/builder/type/union.rb +13 -7
  40. data/lib/gir_ffi/builder/type/with_layout.rb +59 -8
  41. data/lib/gir_ffi/class_base.rb +8 -1
  42. data/lib/gir_ffi/in_out_pointer.rb +17 -18
  43. data/lib/gir_ffi/in_pointer.rb +8 -1
  44. data/lib/gir_ffi/type_map.rb +12 -0
  45. data/lib/gir_ffi/variable_name_generator.rb +12 -0
  46. data/lib/gir_ffi/version.rb +1 -1
  47. data/test/ffi-glib/array_test.rb +54 -0
  48. data/test/ffi-glib/byte_array_test.rb +21 -0
  49. data/test/ffi-glib/glib_overrides_test.rb +1 -46
  50. data/test/ffi-glib/hash_table_test.rb +24 -0
  51. data/test/ffi-glib/list_test.rb +46 -0
  52. data/test/ffi-glib/ptr_array_test.rb +51 -0
  53. data/test/ffi-glib/s_list_test.rb +46 -0
  54. data/test/ffi-gobject/g_object_overrides_test.rb +8 -8
  55. data/test/ffi-gobject/gobject_test.rb +26 -0
  56. data/test/ffi-gobject/object_test.rb +12 -0
  57. data/test/ffi-gobject_introspection/i_constant_info_test.rb +5 -1
  58. data/test/ffi-gobject_introspection/lib_test.rb +56 -0
  59. data/test/integration/generated_gimarshallingtests_test.rb +118 -76
  60. data/test/integration/generated_regress_test.rb +220 -62
  61. data/test/integration/pretty_print_test.rb +11 -0
  62. data/test/type_builder_test.rb +0 -48
  63. data/test/unintrospectable_type_builder_test.rb +8 -2
  64. data/test/unit/builder_test.rb +1 -1
  65. data/test/unit/callback_builder_test.rb +19 -0
  66. data/test/unit/constant_builder_test.rb +11 -0
  67. data/test/unit/enum_builder_test.rb +25 -0
  68. data/test/unit/function_builder_test.rb +17 -0
  69. data/test/unit/in_out_pointer_test.rb +11 -0
  70. data/test/unit/in_pointer_test.rb +6 -2
  71. data/test/unit/interface_builder_test.rb +17 -0
  72. data/test/unit/module_builder_test.rb +95 -0
  73. data/test/unit/object_type_builder_test.rb +24 -0
  74. data/test/unit/struct_builder_test.rb +106 -0
  75. data/test/unit/union_builder_test.rb +17 -0
  76. data/test/unit/variable_name_generator_test.rb +16 -0
  77. metadata +102 -75
  78. data/test/module_builder_test.rb +0 -53
@@ -17,13 +17,13 @@ module GirFFI
17
17
 
18
18
  attr_accessor :length_arg, :array_arg
19
19
 
20
- def initialize function_builder, arginfo=nil, libmodule=nil
21
- @arginfo = arginfo
20
+ def initialize var_gen, name, typeinfo, libmodule
21
+ @typeinfo = typeinfo
22
22
  @inarg = nil
23
23
  @callarg = nil
24
24
  @retname = nil
25
- @name = nil
26
- @function_builder = function_builder
25
+ @name = safe(name)
26
+ @var_gen = var_gen
27
27
  @libmodule = libmodule
28
28
  @length_arg = nil
29
29
  @array_arg = nil
@@ -32,7 +32,7 @@ module GirFFI
32
32
  def prepare; end
33
33
 
34
34
  def type_info
35
- @arginfo.argument_type
35
+ @typeinfo
36
36
  end
37
37
 
38
38
  def type_tag
@@ -4,13 +4,13 @@ module GirFFI
4
4
  # Abstract base class implementing argument processing for arguments
5
5
  # with direction :in.
6
6
  class InBase < Base
7
+ # FIXME: Make class work without 'prepare' stage.
7
8
  def prepare
8
- @name = safe(@arginfo.name)
9
9
  @inarg = @name
10
10
  end
11
11
 
12
12
  def callarg
13
- @callarg ||= @function_builder.new_var
13
+ @callarg ||= @var_gen.new_var
14
14
  end
15
15
  end
16
16
  end
@@ -5,16 +5,15 @@ module GirFFI
5
5
  # with direction :inout.
6
6
  class InOutBase < Base
7
7
  def prepare
8
- @name = safe(@arginfo.name)
9
8
  @inarg = @name
10
9
  end
11
10
 
12
11
  def callarg
13
- @callarg ||= @function_builder.new_var
12
+ @callarg ||= @var_gen.new_var
14
13
  end
15
14
 
16
15
  def retname
17
- @retname ||= @function_builder.new_var
16
+ @retname ||= @var_gen.new_var
18
17
  end
19
18
  end
20
19
  end
@@ -5,15 +5,14 @@ module GirFFI
5
5
  # with direction :out.
6
6
  class OutBase < Base
7
7
  def prepare
8
- @name = safe(@arginfo.name)
9
8
  end
10
9
 
11
10
  def callarg
12
- @callarg ||= @function_builder.new_var
11
+ @callarg ||= @var_gen.new_var
13
12
  end
14
13
 
15
14
  def retname
16
- @retname ||= @function_builder.new_var
15
+ @retname ||= @var_gen.new_var
17
16
  end
18
17
 
19
18
  def pre
@@ -1,4 +1,5 @@
1
1
  require 'gir_ffi/builder/argument'
2
+ require 'gir_ffi/variable_name_generator'
2
3
 
3
4
  module GirFFI::Builder
4
5
  # Implements the creation of a Ruby function definition out of a GIR
@@ -10,9 +11,9 @@ module GirFFI::Builder
10
11
  end
11
12
 
12
13
  def generate
13
- setup_accumulators
14
- @data = @info.args.map {|arg| Argument.build self, arg, @libmodule}
15
- @rvdata = ReturnValue.build self, @info
14
+ vargen = GirFFI::VariableNameGenerator.new
15
+ @data = @info.args.map {|arg| Argument.build vargen, arg, @libmodule}
16
+ @rvdata = ReturnValue.build vargen, @info
16
17
 
17
18
  alldata = @data.dup << @rvdata
18
19
 
@@ -25,19 +26,19 @@ module GirFFI::Builder
25
26
  end
26
27
  }
27
28
 
28
- adjust_accumulators
29
+ setup_error_argument vargen
29
30
  return filled_out_template
30
31
  end
31
32
 
32
- private
33
-
34
- def setup_accumulators
35
- @varno = 0
33
+ def pretty_print
34
+ generate
36
35
  end
37
36
 
38
- def adjust_accumulators
37
+ private
38
+
39
+ def setup_error_argument vargen
39
40
  klass = @info.throws? ? ErrorArgument : NullArgument
40
- @errarg = klass.new(self)
41
+ @errarg = klass.new vargen, nil, nil, nil
41
42
  @errarg.prepare
42
43
  end
43
44
 
@@ -87,12 +88,5 @@ module GirFFI::Builder
87
88
 
88
89
  po.flatten
89
90
  end
90
-
91
- def new_var
92
- @varno += 1
93
- "_v#{@varno}"
94
- end
95
-
96
- public :new_var
97
91
  end
98
92
  end
@@ -1,6 +1,7 @@
1
1
  require 'gir_ffi/builder_helper'
2
2
  require 'gir_ffi/module_base'
3
3
  require 'gir_ffi/builder/function'
4
+ require 'indentation'
4
5
 
5
6
  module GirFFI
6
7
  # Builds a module based on information found in the introspection
@@ -37,6 +38,10 @@ module GirFFI
37
38
 
38
39
  def build_namespaced_class classname
39
40
  info = gir.find_by_name @namespace, classname.to_s
41
+ if info.nil?
42
+ raise NameError.new(
43
+ "Class #{classname} not found in namespace #{@namespace}")
44
+ end
40
45
  Builder.build_class info
41
46
  end
42
47
 
@@ -57,6 +62,15 @@ module GirFFI
57
62
  @module
58
63
  end
59
64
 
65
+ def pretty_print
66
+ s = "module #{@safe_namespace}\n"
67
+ gir.infos(@namespace).each do |info|
68
+ s << sub_builder(info).pretty_print.indent
69
+ s << "\n"
70
+ end
71
+ s << "end"
72
+ end
73
+
60
74
  private
61
75
 
62
76
  def build_dependencies
@@ -95,6 +109,18 @@ module GirFFI
95
109
  optionally_define_constant(@lib, :CALLBACKS) { [] }
96
110
  end
97
111
 
112
+ def sub_builder info
113
+ if info.info_type == :function
114
+ Builder::Function.new(info, libmodule)
115
+ else
116
+ Builder::Type.builder_for info
117
+ end
118
+ end
119
+
120
+ def libmodule
121
+ @module.const_get(:Lib)
122
+ end
123
+
98
124
  def function_introspection_data function
99
125
  info = gir.find_by_name @namespace, function.to_s
100
126
  return nil if info.nil?
@@ -27,6 +27,11 @@ module GirFFI
27
27
  def self.build info
28
28
  TYPE_MAP[info.info_type].new(info).build_class
29
29
  end
30
+
31
+ # TODO: Pull up to include :function and :module
32
+ def self.builder_for info
33
+ TYPE_MAP[info.info_type].new(info)
34
+ end
30
35
  end
31
36
  end
32
37
  end
@@ -1,6 +1,8 @@
1
1
  module GirFFI
2
2
  module Builder
3
3
  module Type
4
+
5
+ # Base class for type builders.
4
6
  class Base
5
7
  include BuilderHelper
6
8
 
@@ -9,11 +9,26 @@ module GirFFI
9
9
  class Callback < Base
10
10
  def instantiate_class
11
11
  @klass = optionally_define_constant namespace_module, @classname do
12
- args = Builder.ffi_function_argument_types info
13
- ret = Builder.ffi_function_return_type info
14
- lib.callback @classname.to_sym, args, ret
12
+ lib.callback callback_sym, argument_types, return_type
15
13
  end
16
14
  end
15
+
16
+ def pretty_print
17
+ return "#{@classname} = Lib.callback #{callback_sym.inspect}, " +
18
+ "#{argument_types.inspect}, #{return_type.inspect}"
19
+ end
20
+
21
+ def callback_sym
22
+ @classname.to_sym
23
+ end
24
+
25
+ def argument_types
26
+ Builder.ffi_function_argument_types info
27
+ end
28
+
29
+ def return_type
30
+ Builder.ffi_function_return_type info
31
+ end
17
32
  end
18
33
  end
19
34
  end
@@ -8,23 +8,15 @@ module GirFFI
8
8
  # triggered by a missing constant in the parent namespace. The
9
9
  # constant will be attached to the appropriate namespace module.
10
10
  class Constant < Base
11
- TYPE_TAG_TO_UNION_MEMBER = {
12
- :gint32 => :v_int32,
13
- :gdouble => :v_double,
14
- :utf8 => :v_string
15
- }
11
+ def pretty_print
12
+ "#{@classname} = #{info.value.inspect}"
13
+ end
16
14
 
17
15
  private
18
16
 
19
17
  def instantiate_class
20
18
  @klass = optionally_define_constant namespace_module, @classname do
21
- tag = info.constant_type.tag
22
- val = info.value[TYPE_TAG_TO_UNION_MEMBER[tag]]
23
- if RUBY_VERSION >= "1.9" and tag == :utf8
24
- val.force_encoding("utf-8")
25
- else
26
- val
27
- end
19
+ info.value
28
20
  end
29
21
  end
30
22
  end
@@ -7,8 +7,16 @@ module GirFFI
7
7
  # attached to the appropriate namespace module, and will be defined
8
8
  # as an enum for FFI.
9
9
  class Enum < RegisteredType
10
+ def pretty_print
11
+ "#{@classname} = Lib.enum #{enum_sym.inspect}, #{value_spec.inspect}"
12
+ end
13
+
10
14
  private
11
15
 
16
+ def enum_sym
17
+ @classname.to_sym
18
+ end
19
+
12
20
  def value_spec
13
21
  return info.values.map {|vinfo|
14
22
  val = GirFFI::ArgHelper.cast_uint32_to_int32(vinfo.value)
@@ -17,13 +25,14 @@ module GirFFI
17
25
  end
18
26
 
19
27
  def instantiate_class
20
- if const_defined_for namespace_module, @classname
21
- @klass = namespace_module.const_get @classname
22
- else
23
- @klass = namespace_module.const_set @classname,
24
- lib.enum(@classname.to_sym, value_spec)
25
- setup_gtype_getter
28
+ @klass = optionally_define_constant namespace_module, @classname do
29
+ lib.enum(enum_sym, value_spec)
26
30
  end
31
+ setup_gtype_getter unless already_set_up
32
+ end
33
+
34
+ def already_set_up
35
+ @klass.respond_to? :get_gtype
27
36
  end
28
37
  end
29
38
  end
@@ -10,6 +10,10 @@ module GirFFI
10
10
  class Interface < RegisteredType
11
11
  include WithMethods
12
12
 
13
+ def pretty_print
14
+ "module #{@classname}\n extend InterfaceBase\nend"
15
+ end
16
+
13
17
  private
14
18
 
15
19
  # FIXME: The word 'class' is not really correct.
@@ -34,6 +34,17 @@ module GirFFI
34
34
  if parent
35
35
  return superclass._find_signal signal_name
36
36
  end
37
+ raise "Signal #{signal_name} not found"
38
+ end
39
+
40
+ def find_property property_name
41
+ info.properties.each do |prop|
42
+ return prop if prop.name == property_name
43
+ end
44
+ if parent
45
+ return superclass._find_property property_name
46
+ end
47
+ raise "Property #{property_name} not found"
37
48
  end
38
49
 
39
50
  private
@@ -12,12 +12,22 @@ module GirFFI
12
12
  include WithMethods
13
13
  include WithLayout
14
14
 
15
+ def pretty_print
16
+ "class #{@classname}\nend"
17
+ end
18
+
15
19
  private
16
20
 
17
- def instantiate_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
+ def setup_class
22
+ setup_layout
23
+ setup_constants
24
+ stub_methods
25
+ setup_gtype_getter
26
+ setup_field_accessors
27
+ end
28
+
29
+ def layout_superclass
30
+ FFI::Struct
21
31
  end
22
32
  end
23
33
  end
@@ -12,18 +12,24 @@ module GirFFI
12
12
  include WithMethods
13
13
  include WithLayout
14
14
 
15
- private
16
-
17
- def instantiate_class
18
- @klass = get_or_define_class namespace_module, @classname, superclass
19
- @structklass = get_or_define_class @klass, :Struct, FFI::Union
20
- setup_class unless already_set_up
15
+ def pretty_print
16
+ "class #{@classname}\nend"
21
17
  end
22
18
 
19
+ private
20
+
23
21
  def setup_class
24
- super
22
+ setup_layout
23
+ setup_constants
24
+ stub_methods
25
+ setup_gtype_getter
26
+ setup_field_accessors
25
27
  provide_constructor
26
28
  end
29
+
30
+ def layout_superclass
31
+ FFI::Union
32
+ end
27
33
  end
28
34
  end
29
35
  end
@@ -1,3 +1,6 @@
1
+ require 'gir_ffi/builder/argument'
2
+ require 'gir_ffi/variable_name_generator'
3
+
1
4
  module GirFFI
2
5
  module Builder
3
6
  module Type
@@ -7,14 +10,6 @@ module GirFFI
7
10
  module WithLayout
8
11
  private
9
12
 
10
- # TODO: Move to client classes.
11
- def setup_class
12
- setup_layout
13
- setup_constants
14
- stub_methods
15
- setup_gtype_getter
16
- end
17
-
18
13
  def setup_layout
19
14
  spec = layout_specification
20
15
  @structklass.class_eval { layout(*spec) }
@@ -38,6 +33,62 @@ module GirFFI
38
33
  finfo.offset ]
39
34
  end
40
35
  end
36
+
37
+ def setup_field_accessors
38
+ info.fields.each do |finfo|
39
+ unless info.find_method finfo.name
40
+ @klass.class_eval getter_def(finfo)
41
+ end
42
+ @klass.class_eval setter_def(finfo) if finfo.writable?
43
+ end
44
+ end
45
+
46
+ # TODO: Extract to new FieldBuilder class.
47
+ def getter_builder finfo
48
+ type = finfo.field_type
49
+ klass = Builder::ReturnValue.builder_for_field_getter type
50
+ vargen = VariableNameGenerator.new
51
+ klass.new vargen, finfo.name, type, nil
52
+ end
53
+
54
+ def getter_def finfo
55
+ builder = getter_builder finfo
56
+ name = finfo.name
57
+
58
+ return <<-CODE
59
+ def #{name}
60
+ #{builder.cvar} = @struct[#{name.to_sym.inspect}]
61
+ #{builder.post.join("\n")}
62
+ #{builder.retval}
63
+ end
64
+ CODE
65
+ end
66
+
67
+ def setter_builder finfo
68
+ type = finfo.field_type
69
+ klass = Builder::InArgument.builder_for type
70
+ vargen = VariableNameGenerator.new
71
+ klass.new vargen, "value", type, lib
72
+ end
73
+
74
+ def setter_def finfo
75
+ builder = setter_builder finfo
76
+ builder.prepare
77
+ name = finfo.name
78
+
79
+ return <<-CODE
80
+ def #{name}= #{builder.inarg}
81
+ #{builder.pre.join("\n")}
82
+ @struct[#{name.to_sym.inspect}] = #{builder.callarg}
83
+ end
84
+ CODE
85
+ end
86
+
87
+ def instantiate_class
88
+ @klass = get_or_define_class namespace_module, @classname, superclass
89
+ @structklass = get_or_define_class @klass, :Struct, layout_superclass
90
+ setup_class unless already_set_up
91
+ end
41
92
  end
42
93
  end
43
94
  end