gir_ffi 0.0.10 → 0.0.11

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.
Files changed (73) hide show
  1. data/History.txt +11 -0
  2. data/README.rdoc +28 -14
  3. data/Rakefile +1 -1
  4. data/TODO.rdoc +3 -24
  5. data/examples/05_notification.rb +35 -0
  6. data/lib/gir_ffi/arg_helper.rb +15 -279
  7. data/lib/gir_ffi/builder/argument/base.rb +110 -0
  8. data/lib/gir_ffi/builder/argument/hash_table_base.rb +20 -0
  9. data/lib/gir_ffi/builder/argument/in_base.rb +19 -0
  10. data/lib/gir_ffi/builder/argument/in_out_base.rb +25 -0
  11. data/lib/gir_ffi/builder/argument/list_base.rb +16 -0
  12. data/lib/gir_ffi/builder/argument/out_base.rb +27 -0
  13. data/lib/gir_ffi/builder/argument.rb +167 -357
  14. data/lib/gir_ffi/builder/function.rb +2 -0
  15. data/lib/gir_ffi/builder/module.rb +2 -2
  16. data/lib/gir_ffi/builder/type/base.rb +7 -0
  17. data/lib/gir_ffi/builder/type/callback.rb +1 -8
  18. data/lib/gir_ffi/builder/type/constant.rb +1 -6
  19. data/lib/gir_ffi/builder/type/enum.rb +2 -7
  20. data/lib/gir_ffi/builder/type/interface.rb +12 -14
  21. data/lib/gir_ffi/builder/type/object.rb +32 -13
  22. data/lib/gir_ffi/builder/type/registered_type.rb +1 -78
  23. data/lib/gir_ffi/builder/type/struct.rb +2 -0
  24. data/lib/gir_ffi/builder/type/struct_based.rb +9 -24
  25. data/lib/gir_ffi/builder/type/unintrospectable.rb +63 -0
  26. data/lib/gir_ffi/builder/type/union.rb +8 -7
  27. data/lib/gir_ffi/builder/type/with_layout.rb +43 -0
  28. data/lib/gir_ffi/builder/type/with_methods.rb +61 -0
  29. data/lib/gir_ffi/builder.rb +39 -0
  30. data/lib/gir_ffi/callback_helper.rb +58 -0
  31. data/lib/gir_ffi/class_base.rb +17 -5
  32. data/lib/gir_ffi/i_repository.rb +0 -4
  33. data/lib/gir_ffi/in_out_pointer.rb +76 -0
  34. data/lib/gir_ffi/in_pointer.rb +46 -0
  35. data/lib/gir_ffi/interface_base.rb +12 -0
  36. data/lib/gir_ffi/module_base.rb +7 -3
  37. data/lib/gir_ffi/overrides/glib.rb +14 -3
  38. data/lib/gir_ffi/overrides/gobject.rb +37 -15
  39. data/lib/gir_ffi/overrides/gtk.rb +1 -1
  40. data/lib/gir_ffi/version.rb +1 -1
  41. data/lib/gir_ffi.rb +3 -0
  42. data/tasks/rdoc.rake +6 -0
  43. data/tasks/test.rake +22 -3
  44. data/tasks/yardoc.rake +6 -0
  45. data/test/arg_helper_test.rb +2 -72
  46. data/test/builder_test.rb +15 -19
  47. data/test/function_definition_builder_test.rb +30 -37
  48. data/test/g_object_overrides_test.rb +29 -1
  49. data/test/glib_overrides_test.rb +4 -0
  50. data/test/gtk_overrides_test.rb +21 -15
  51. data/test/i_repository_test.rb +2 -1
  52. data/test/{generated_gimarshallingtests_test.rb → integration/generated_gimarshallingtests_test.rb} +1 -1
  53. data/test/integration/generated_gio_test.rb +98 -0
  54. data/test/integration/generated_gobject_test.rb +30 -0
  55. data/test/{generated_gtk_test.rb → integration/generated_gtk_test.rb} +5 -5
  56. data/test/{generated_regress_test.rb → integration/generated_regress_test.rb} +19 -5
  57. data/test/interface_type_builder_test.rb +1 -1
  58. data/test/module_builder_test.rb +3 -3
  59. data/test/test_helper.rb +4 -9
  60. data/test/type_builder_test.rb +5 -5
  61. data/test/{dynamic_type_builder_test.rb → unintrospectable_type_builder_test.rb} +12 -8
  62. data/test/unit/builder_test.rb +31 -0
  63. data/test/unit/callback_helper_test.rb +19 -0
  64. data/test/unit/constant_builder_test.rb +5 -0
  65. data/test/unit/i_constant_info_test.rb +17 -0
  66. data/test/unit/in_out_pointer_test.rb +118 -0
  67. data/test/unit/in_pointer_test.rb +69 -0
  68. data/test/unit/object_type_builder_test.rb +20 -0
  69. metadata +47 -19
  70. data/lib/gir_ffi/builder/dynamic_type.rb +0 -41
  71. data/test/generated_gio_test.rb +0 -39
  72. data/test/generated_gobject_test.rb +0 -15
  73. data/test/object_type_builder_test.rb +0 -34
@@ -80,6 +80,8 @@ module GirFFI::Builder
80
80
  po = (@data.map(&:post) + @data.map(&:postpost) + @rvdata.post)
81
81
  po.unshift @errarg.post
82
82
 
83
+ po += @data.map {|d| d.cleanup}
84
+
83
85
  retvals = ([@rvdata.retval] + @data.map(&:retval)).compact
84
86
  po << "return #{retvals.join(', ')}" unless retvals.empty?
85
87
 
@@ -18,7 +18,7 @@ module GirFFI
18
18
  build_module
19
19
  end
20
20
 
21
- def setup_function method
21
+ def setup_method method
22
22
  go = function_introspection_data method.to_s
23
23
 
24
24
  return false if go.nil?
@@ -34,7 +34,7 @@ module GirFFI
34
34
  true
35
35
  end
36
36
 
37
- def build_class classname
37
+ def build_namespaced_class classname
38
38
  info = gir.find_by_name @namespace, classname.to_s
39
39
  Builder.build_class info
40
40
  end
@@ -10,6 +10,13 @@ module GirFFI
10
10
  @classname = @info.name.gsub(/^(.)/) { $1.upcase }
11
11
  end
12
12
 
13
+ def build_class
14
+ unless defined? @klass
15
+ instantiate_class
16
+ end
17
+ @klass
18
+ end
19
+
13
20
  private
14
21
 
15
22
  def info
@@ -7,14 +7,7 @@ module GirFFI
7
7
  # attached to the appropriate namespace module, and will be defined
8
8
  # as a callback for FFI.
9
9
  class Callback < Base
10
- def build_class
11
- unless defined? @klass
12
- instantiate_callback_class
13
- end
14
- @klass
15
- end
16
-
17
- def instantiate_callback_class
10
+ def instantiate_class
18
11
  @klass = optionally_define_constant namespace_module, @classname do
19
12
  args = Builder.ffi_function_argument_types info
20
13
  ret = Builder.ffi_function_return_type info
@@ -14,12 +14,7 @@ module GirFFI
14
14
  :utf8 => :v_string
15
15
  }
16
16
 
17
- def build_class
18
- unless defined? @klass
19
- instantiate_class
20
- end
21
- @klass
22
- end
17
+ private
23
18
 
24
19
  def instantiate_class
25
20
  @klass = optionally_define_constant namespace_module, @classname do
@@ -7,12 +7,7 @@ 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 build_class
11
- unless defined? @klass
12
- instantiate_enum_class
13
- end
14
- @klass
15
- end
10
+ private
16
11
 
17
12
  def value_spec
18
13
  return info.values.map {|vinfo|
@@ -21,7 +16,7 @@ module GirFFI
21
16
  }.flatten
22
17
  end
23
18
 
24
- def instantiate_enum_class
19
+ def instantiate_class
25
20
  if const_defined_for namespace_module, @classname
26
21
  @klass = namespace_module.const_get @classname
27
22
  else
@@ -1,29 +1,27 @@
1
- require 'gir_ffi/builder/type/struct_based'
1
+ require 'gir_ffi/builder/type/registered_type'
2
+ require 'gir_ffi/builder/type/with_methods'
3
+ require 'gir_ffi/interface_base'
4
+
2
5
  module GirFFI
3
6
  module Builder
4
7
  module Type
5
8
 
6
- # Implements the creation of a class representing an Interface.
9
+ # Implements the creation of a module representing an Interface.
7
10
  class Interface < RegisteredType
8
- def build_class
9
- unless defined? @klass
10
- instantiate_module
11
- end
12
- @klass
13
- end
11
+ include WithMethods
12
+
13
+ private
14
14
 
15
- def instantiate_module
15
+ # FIXME: The word 'class' is not really correct.
16
+ def instantiate_class
16
17
  @klass = optionally_define_constant(namespace_module, @classname) do
17
- ::Module.new do
18
- def self.gir_ffi_builder
19
- const_get :GIR_FFI_BUILDER
20
- end
21
- end
18
+ ::Module.new
22
19
  end
23
20
  setup_module unless already_set_up
24
21
  end
25
22
 
26
23
  def setup_module
24
+ @klass.extend InterfaceBase
27
25
  setup_constants
28
26
  stub_methods
29
27
  end
@@ -10,7 +10,7 @@ module GirFFI
10
10
  return true
11
11
  else
12
12
  if parent
13
- return superclass.gir_ffi_builder.setup_method method
13
+ return superclass._setup_method method
14
14
  else
15
15
  return false
16
16
  end
@@ -21,22 +21,36 @@ module GirFFI
21
21
  if super
22
22
  return true
23
23
  else
24
- info.interfaces.each do |ifinfo|
25
- iface = GirFFI::Builder.build_class ifinfo
26
- if iface.gir_ffi_builder.setup_instance_method method
27
- return true
28
- end
29
- end
30
- if parent
31
- return superclass.gir_ffi_builder.setup_instance_method method
32
- else
33
- return false
24
+ setup_instance_method_in_ancestor method
25
+ end
26
+ end
27
+
28
+ def find_signal signal_name
29
+ signal_definers.each do |inf|
30
+ inf.signals.each do |sig|
31
+ return sig if sig.name == signal_name
34
32
  end
35
33
  end
34
+ if parent
35
+ return superclass._find_signal signal_name
36
+ end
36
37
  end
37
38
 
38
39
  private
39
40
 
41
+ def setup_instance_method_in_ancestor method
42
+ interfaces.each do |iface|
43
+ if iface._setup_instance_method method
44
+ return true
45
+ end
46
+ end
47
+ if parent
48
+ return superclass._setup_instance_method method
49
+ else
50
+ return false
51
+ end
52
+ end
53
+
40
54
  def setup_class
41
55
  super
42
56
  setup_vfunc_invokers
@@ -70,8 +84,7 @@ module GirFFI
70
84
  end
71
85
 
72
86
  def setup_interfaces
73
- info.interfaces.each do |ifinfo|
74
- iface = GirFFI::Builder.build_class ifinfo
87
+ interfaces.each do |iface|
75
88
  @klass.class_eval do
76
89
  include iface
77
90
  end
@@ -81,6 +94,12 @@ module GirFFI
81
94
  def signal_definers
82
95
  [info] + info.interfaces
83
96
  end
97
+
98
+ def interfaces
99
+ info.interfaces.map do |ifinfo|
100
+ GirFFI::Builder.build_class ifinfo
101
+ end
102
+ end
84
103
  end
85
104
  end
86
105
  end
@@ -9,72 +9,8 @@ module GirFFI
9
9
  # of IRegisteredTypeInfo. These are types whose C representation is
10
10
  # complex, i.e., a struct or a union.
11
11
  class RegisteredType < Base
12
- def setup_method method
13
- klass = build_class
14
- meta = (class << klass; self; end)
15
-
16
- go = method_introspection_data method
17
- attach_and_define_method method, go, meta
18
- end
19
-
20
- def setup_instance_method method
21
- go = instance_method_introspection_data method
22
- attach_and_define_method method, go, build_class
23
- end
24
-
25
12
  private
26
13
 
27
- def method_introspection_data method
28
- info.find_method method
29
- end
30
-
31
- def instance_method_introspection_data method
32
- data = method_introspection_data method
33
- return !data.nil? && data.method? ? data : nil
34
- end
35
-
36
- def function_definition go
37
- Builder::Function.new(go, lib).generate
38
- end
39
-
40
- def attach_and_define_method method, go, modul
41
- return false if go.nil?
42
- Builder.attach_ffi_function lib, go
43
- modul.class_eval { remove_method method }
44
- modul.class_eval function_definition(go)
45
- true
46
- end
47
-
48
- def setup_class
49
- setup_layout
50
- setup_constants
51
- stub_methods
52
- setup_gtype_getter
53
- end
54
-
55
- def setup_layout
56
- spec = layout_specification
57
- @structklass.class_eval { layout(*spec) }
58
- end
59
-
60
- def layout_specification
61
- fields = info.fields
62
-
63
- if fields.empty?
64
- if parent
65
- return [:parent, superclass.const_get(:Struct), 0]
66
- else
67
- return [:dummy, :char, 0]
68
- end
69
- end
70
-
71
- fields.map do |finfo|
72
- [ finfo.name.to_sym,
73
- itypeinfo_to_ffitype_for_struct(finfo.field_type),
74
- finfo.offset ]
75
- end.flatten
76
- end
77
-
78
14
  # FIXME: Move this into a class with the other type knowledge.
79
15
  def itypeinfo_to_ffitype_for_struct typeinfo
80
16
  ffitype = Builder.itypeinfo_to_ffitype typeinfo
@@ -96,21 +32,8 @@ module GirFFI
96
32
  const_defined_for @klass, :GIR_FFI_BUILDER
97
33
  end
98
34
 
99
- def stub_methods
100
- info.get_methods.each do |minfo|
101
- @klass.class_eval method_stub(minfo.name, minfo.method?)
102
- end
103
- end
104
-
105
- def method_stub symbol, is_instance_method
106
- "
107
- def #{is_instance_method ? '' : 'self.'}#{symbol} *args, &block
108
- setup_and_call :#{symbol}, *args, &block
109
- end
110
- "
111
- end
112
-
113
35
  # TODO: Rename the created method, or use a constant.
36
+ # FIXME: Only used in some of the subclases. Make mixin?
114
37
  def setup_gtype_getter
115
38
  gtype = info.g_type
116
39
  return if gtype.nil?
@@ -5,6 +5,8 @@ module GirFFI
5
5
 
6
6
  # Implements the creation of a class representing a Struct.
7
7
  class Struct < StructBased
8
+ private
9
+
8
10
  def setup_class
9
11
  super
10
12
  provide_constructor
@@ -1,39 +1,24 @@
1
1
  require 'gir_ffi/builder/type/registered_type'
2
+ require 'gir_ffi/builder/type/with_layout'
3
+ require 'gir_ffi/builder/type/with_methods'
4
+
2
5
  module GirFFI
3
6
  module Builder
4
7
  module Type
5
8
 
6
9
  # 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.
10
+ # whose C representation is a struct, i.e., :object and :struct.
9
11
  class StructBased < RegisteredType
10
- def build_class
11
- unless defined? @klass
12
- instantiate_struct_class
13
- end
14
- @klass
15
- end
12
+ include WithMethods
13
+ include WithLayout
16
14
 
17
- def instantiate_struct_class
15
+ private
16
+
17
+ def instantiate_class
18
18
  @klass = get_or_define_class namespace_module, @classname, superclass
19
19
  @structklass = get_or_define_class @klass, :Struct, FFI::Struct
20
20
  setup_class unless already_set_up
21
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
22
  end
38
23
  end
39
24
  end
@@ -0,0 +1,63 @@
1
+ require 'gir_ffi/builder/type/object'
2
+ module GirFFI
3
+ module Builder
4
+ module Type
5
+
6
+ # Implements the creation of a class representing an object type for
7
+ # which no data is found in the GIR. Typically, these are created to
8
+ # cast objects returned by a function that returns an interface.
9
+ class Unintrospectable < Object
10
+ CACHE = {}
11
+
12
+ # FIXME: Breaks parent interface.
13
+ def initialize gtype
14
+ @gtype = gtype
15
+ @info = nil
16
+ end
17
+
18
+ def instantiate_class
19
+ CACHE[@gtype] ||= Class.new(superclass)
20
+ @klass = CACHE[@gtype]
21
+ setup_class unless already_set_up
22
+ end
23
+
24
+ def setup_class
25
+ setup_constants
26
+ setup_interfaces
27
+ end
28
+
29
+ def setup_instance_method method
30
+ setup_instance_method_in_ancestor method
31
+ end
32
+
33
+ private
34
+
35
+ def parent
36
+ parent_type = ::GObject.type_parent @gtype
37
+ gir.find_by_gtype(parent_type)
38
+ end
39
+
40
+ def interface_infos
41
+ ::GObject.type_interfaces(@gtype).map do |gtype|
42
+ gir.find_by_gtype gtype
43
+ end
44
+ end
45
+
46
+ def interfaces
47
+ interface_infos.map do |info|
48
+ GirFFI::Builder.build_class info
49
+ end
50
+ end
51
+
52
+ def signal_definers
53
+ interface_infos
54
+ end
55
+
56
+ def gir
57
+ @gir ||= GirFFI::IRepository.default
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+
@@ -1,4 +1,7 @@
1
1
  require 'gir_ffi/builder/type/registered_type'
2
+ require 'gir_ffi/builder/type/with_layout'
3
+ require 'gir_ffi/builder/type/with_methods'
4
+
2
5
  module GirFFI
3
6
  module Builder
4
7
  module Type
@@ -6,14 +9,12 @@ module GirFFI
6
9
  # Implements the creation of a class representing union type. The
7
10
  # class will have a nested FFI::Union class to represent its C union.
8
11
  class Union < RegisteredType
9
- def build_class
10
- unless defined? @klass
11
- instantiate_union_class
12
- end
13
- @klass
14
- end
12
+ include WithMethods
13
+ include WithLayout
14
+
15
+ private
15
16
 
16
- def instantiate_union_class
17
+ def instantiate_class
17
18
  @klass = get_or_define_class namespace_module, @classname, superclass
18
19
  @structklass = get_or_define_class @klass, :Struct, FFI::Union
19
20
  setup_class unless already_set_up
@@ -0,0 +1,43 @@
1
+ module GirFFI
2
+ module Builder
3
+ module Type
4
+
5
+ # Implements the creation of classes representing types with layout,
6
+ # i.e., :union, :struct, :object.
7
+ module WithLayout
8
+ private
9
+
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
+ def setup_layout
19
+ spec = layout_specification
20
+ @structklass.class_eval { layout(*spec) }
21
+ end
22
+
23
+ def layout_specification
24
+ fields = info.fields
25
+
26
+ if fields.empty?
27
+ if parent
28
+ return [:parent, superclass.const_get(:Struct), 0]
29
+ else
30
+ return [:dummy, :char, 0]
31
+ end
32
+ end
33
+
34
+ fields.map do |finfo|
35
+ [ finfo.name.to_sym,
36
+ itypeinfo_to_ffitype_for_struct(finfo.field_type),
37
+ finfo.offset ]
38
+ end.flatten
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,61 @@
1
+ module GirFFI
2
+ module Builder
3
+ module Type
4
+
5
+ # Implements method creation for types such as, :union, :struct,
6
+ # :object, :interface.
7
+ module WithMethods
8
+ def setup_method method
9
+ klass = build_class
10
+ meta = (class << klass; self; end)
11
+
12
+ go = method_introspection_data method
13
+ attach_and_define_method method, go, meta
14
+ end
15
+
16
+ def setup_instance_method method
17
+ go = instance_method_introspection_data method
18
+ attach_and_define_method method, go, build_class
19
+ end
20
+
21
+ private
22
+
23
+ def method_introspection_data method
24
+ info.find_method method
25
+ end
26
+
27
+ def instance_method_introspection_data method
28
+ data = method_introspection_data method
29
+ return !data.nil? && data.method? ? data : nil
30
+ end
31
+
32
+ def function_definition go
33
+ Builder::Function.new(go, lib).generate
34
+ end
35
+
36
+ def attach_and_define_method method, go, modul
37
+ return false if go.nil?
38
+ Builder.attach_ffi_function lib, go
39
+ modul.class_eval { remove_method method }
40
+ modul.class_eval function_definition(go)
41
+ true
42
+ end
43
+
44
+ def stub_methods
45
+ info.get_methods.each do |minfo|
46
+ @klass.class_eval method_stub(minfo.name, minfo.method?)
47
+ end
48
+ end
49
+
50
+ def method_stub symbol, is_instance_method
51
+ "
52
+ def #{is_instance_method ? '' : 'self.'}#{symbol} *args, &block
53
+ setup_and_call :#{symbol}, *args, &block
54
+ end
55
+ "
56
+ end
57
+
58
+ end
59
+ end
60
+ end
61
+ end
@@ -1,4 +1,5 @@
1
1
  require 'gir_ffi/builder/type'
2
+ require 'gir_ffi/builder/type/unintrospectable'
2
3
  require 'gir_ffi/builder/module'
3
4
  require 'gir_ffi/builder_helper'
4
5
 
@@ -9,8 +10,12 @@ module GirFFI
9
10
  module Builder
10
11
  extend BuilderHelper
11
12
 
13
+ sz = FFI.type_size(:size_t) * 8
14
+ gtype_type = "uint#{sz}".to_sym
15
+
12
16
  TAG_TYPE_MAP = {
13
17
  :GType => :size_t,
18
+ :gtype => gtype_type,
14
19
  :gboolean => :bool,
15
20
  :gunichar => :uint32,
16
21
  :gint8 => :int8,
@@ -31,6 +36,15 @@ module GirFFI
31
36
  Builder::Type.build(info)
32
37
  end
33
38
 
39
+ def self.build_by_gtype gtype
40
+ info = IRepository.default.find_by_gtype gtype
41
+ if info.nil?
42
+ Builder::Type::Unintrospectable.new(gtype).build_class
43
+ else
44
+ build_class info
45
+ end
46
+ end
47
+
34
48
  def self.build_module namespace, version=nil
35
49
  Builder::Module.new(namespace, version).generate
36
50
  end
@@ -58,12 +72,37 @@ module GirFFI
58
72
  types
59
73
  end
60
74
 
75
+ def self.ffi_argument_types_for_signal info
76
+ types = info.args.map do |arg|
77
+ itypeinfo_to_callback_ffitype arg.argument_type
78
+ end
79
+ types.unshift(:pointer).push(:pointer)
80
+ end
81
+
61
82
  def self.ffi_function_return_type info
62
83
  rt = info.return_type
63
84
  return :string if rt.tag == :utf8
64
85
  itypeinfo_to_ffitype rt
65
86
  end
66
87
 
88
+ def self.itypeinfo_to_callback_ffitype info
89
+ tag = info.tag
90
+
91
+ return :string if tag == :utf8
92
+ return :pointer if info.pointer?
93
+
94
+ if tag == :interface
95
+ case info.interface.info_type
96
+ when :enum, :flags
97
+ :int32
98
+ else
99
+ :pointer
100
+ end
101
+ else
102
+ return TAG_TYPE_MAP[tag] || tag
103
+ end
104
+ end
105
+
67
106
  def self.itypeinfo_to_ffitype info
68
107
  return :pointer if info.pointer?
69
108