gir_ffi 0.0.10 → 0.0.11

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