gir_ffi 0.2.2 → 0.2.3

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 (69) hide show
  1. data/History.txt +6 -0
  2. data/lib/ffi-glib.rb +1 -0
  3. data/lib/ffi-glib/array.rb +49 -10
  4. data/lib/ffi-glib/hash_table.rb +19 -5
  5. data/lib/ffi-glib/list.rb +4 -1
  6. data/lib/ffi-glib/list_methods.rb +8 -1
  7. data/lib/ffi-glib/s_list.rb +4 -1
  8. data/lib/ffi-glib/strv.rb +31 -0
  9. data/lib/ffi-gobject.rb +2 -35
  10. data/lib/ffi-gobject/base.rb +38 -0
  11. data/lib/ffi-gobject/object.rb +28 -30
  12. data/lib/ffi-gobject/value.rb +72 -56
  13. data/lib/ffi-gobject_introspection/i_struct_info.rb +11 -1
  14. data/lib/ffi-gobject_introspection/lib.rb +3 -1
  15. data/lib/gir_ffi/arg_helper.rb +2 -19
  16. data/lib/gir_ffi/builder/argument.rb +239 -305
  17. data/lib/gir_ffi/builder/argument/base.rb +12 -9
  18. data/lib/gir_ffi/builder/argument/in_base.rb +2 -6
  19. data/lib/gir_ffi/builder/argument/in_out_base.rb +2 -5
  20. data/lib/gir_ffi/builder/argument/out_base.rb +0 -11
  21. data/lib/gir_ffi/builder/field.rb +55 -0
  22. data/lib/gir_ffi/builder/function.rb +7 -7
  23. data/lib/gir_ffi/builder/module.rb +5 -7
  24. data/lib/gir_ffi/builder/type/object.rb +0 -33
  25. data/lib/gir_ffi/builder/type/registered_type.rb +0 -16
  26. data/lib/gir_ffi/builder/type/struct_based.rb +3 -3
  27. data/lib/gir_ffi/builder/type/unintrospectable.rb +1 -1
  28. data/lib/gir_ffi/builder/type/with_layout.rb +26 -58
  29. data/lib/gir_ffi/builder/type/with_methods.rb +9 -11
  30. data/lib/gir_ffi/class_base.rb +24 -6
  31. data/lib/gir_ffi/ffi_ext/pointer.rb +15 -0
  32. data/lib/gir_ffi/in_pointer.rb +10 -5
  33. data/lib/gir_ffi/info_ext/i_field_info.rb +15 -0
  34. data/lib/gir_ffi/info_ext/i_type_info.rb +26 -0
  35. data/lib/gir_ffi/method_stubber.rb +18 -0
  36. data/lib/gir_ffi/type_map.rb +1 -0
  37. data/lib/gir_ffi/variable_name_generator.rb +2 -0
  38. data/lib/gir_ffi/version.rb +1 -1
  39. data/test/builder_test.rb +6 -5
  40. data/test/ffi-glib/array_test.rb +40 -5
  41. data/test/ffi-glib/hash_table_test.rb +27 -3
  42. data/test/ffi-glib/list_test.rb +23 -0
  43. data/test/ffi-glib/strv_test.rb +41 -0
  44. data/test/ffi-gobject/gobject_test.rb +26 -22
  45. data/test/ffi-gobject/value_test.rb +26 -1
  46. data/test/ffi-gobject_introspection/lib_test.rb +10 -0
  47. data/test/gir_ffi_test_helper.rb +1 -1
  48. data/test/integration/derived_classes_test.rb +31 -0
  49. data/test/integration/generated_gimarshallingtests_test.rb +29 -15
  50. data/test/integration/generated_gio_test.rb +5 -6
  51. data/test/integration/generated_regress_test.rb +11 -7
  52. data/test/integration/method_lookup_test.rb +32 -0
  53. data/test/interface_type_builder_test.rb +1 -1
  54. data/test/test_helper.rb +38 -0
  55. data/test/unit/argument_builder_test.rb +16 -4
  56. data/test/unit/class_base_test.rb +48 -0
  57. data/test/unit/function_builder_test.rb +144 -4
  58. data/test/unit/hash_table_element_type_provider_test.rb +16 -0
  59. data/test/unit/i_field_info_test.rb +39 -0
  60. data/test/unit/i_type_info_test.rb +23 -0
  61. data/test/unit/list_element_type_provider_test.rb +13 -0
  62. data/test/unit/module_builder_test.rb +1 -1
  63. data/test/unit/object_type_builder_test.rb +0 -17
  64. data/test/unit/struct_builder_test.rb +27 -39
  65. metadata +118 -60
  66. data/lib/gir_ffi/builder/argument/hash_table_base.rb +0 -20
  67. data/lib/gir_ffi/builder/argument/list_base.rb +0 -16
  68. data/test/class_base_test.rb +0 -10
  69. data/test/function_definition_builder_test.rb +0 -130
@@ -1,3 +1,5 @@
1
+ require 'gir_ffi/method_stubber'
2
+
1
3
  module GirFFI
2
4
  module Builder
3
5
  module Type
@@ -15,6 +17,10 @@ module GirFFI
15
17
  attach_and_define_method method, go, build_class
16
18
  end
17
19
 
20
+ def has_instance_method method
21
+ !!instance_method_introspection_data(method)
22
+ end
23
+
18
24
  private
19
25
 
20
26
  def meta_class
@@ -28,7 +34,7 @@ module GirFFI
28
34
 
29
35
  def instance_method_introspection_data method
30
36
  data = method_introspection_data method
31
- return !data.nil? && data.method? ? data : nil
37
+ return data if data && data.method?
32
38
  end
33
39
 
34
40
  def function_definition_builder go
@@ -43,24 +49,16 @@ module GirFFI
43
49
  return false if go.nil?
44
50
  Builder.attach_ffi_function lib, go
45
51
  modul.class_eval { remove_method method }
46
- modul.class_eval function_definition(go)
52
+ build_class.class_eval function_definition(go)
47
53
  true
48
54
  end
49
55
 
50
56
  def stub_methods
51
57
  info.get_methods.each do |minfo|
52
- @klass.class_eval method_stub(minfo.name, minfo.method?)
58
+ @klass.class_eval MethodStubber.new(minfo).method_stub
53
59
  end
54
60
  end
55
61
 
56
- def method_stub symbol, is_instance_method
57
- "
58
- def #{is_instance_method ? '' : 'self.'}#{symbol} *args, &block
59
- setup_and_call :#{symbol}, *args, &block
60
- end
61
- "
62
- end
63
-
64
62
  def pretty_print_methods
65
63
  info.get_methods.map do |minfo|
66
64
  function_definition_builder(minfo).pretty_print.indent + "\n"
@@ -1,4 +1,6 @@
1
1
  require 'forwardable'
2
+ require 'gir_ffi/ffi_ext/pointer'
3
+
2
4
  module GirFFI
3
5
  # Base class for all generated classes. Contains code for dealing with
4
6
  # the generated Struct classes.
@@ -20,16 +22,28 @@ module GirFFI
20
22
  end
21
23
 
22
24
  def setup_and_call method, *arguments, &block
23
- unless _builder.setup_instance_method method.to_s
25
+ result = self.class.ancestors.any? do |klass|
26
+ klass.respond_to?(:_setup_instance_method) &&
27
+ klass._setup_instance_method(method.to_s)
28
+ end
29
+
30
+ unless result
24
31
  raise RuntimeError, "Unable to set up instance method #{method} in #{self}"
25
32
  end
33
+
26
34
  self.send method, *arguments, &block
27
35
  end
28
36
 
29
37
  def self.setup_and_call method, *arguments, &block
30
- unless _builder.setup_method method.to_s
38
+ result = self.ancestors.any? do |klass|
39
+ klass.respond_to?(:_setup_method) &&
40
+ klass._setup_method(method.to_s)
41
+ end
42
+
43
+ unless result
31
44
  raise RuntimeError, "Unable to set up method #{method} in #{self}"
32
45
  end
46
+
33
47
  self.send method, *arguments, &block
34
48
  end
35
49
 
@@ -67,10 +81,7 @@ module GirFFI
67
81
 
68
82
  def wrap ptr
69
83
  return nil if ptr.nil? or ptr.null?
70
- unless ptr.is_a? FFI::Pointer
71
- ptr = ptr.to_ptr
72
- end
73
- _real_new ptr
84
+ _real_new ptr.to_ptr
74
85
  end
75
86
 
76
87
  # TODO: Only makes sense for :objects.
@@ -81,6 +92,13 @@ module GirFFI
81
92
  def allocate
82
93
  _real_new
83
94
  end
95
+
96
+ # Pass-through casting method. This may become a type checking
97
+ # method. It is overridden by GValue to implement wrapping of plain
98
+ # Ruby objects.
99
+ def from val
100
+ val
101
+ end
84
102
  end
85
103
  end
86
104
  end
@@ -0,0 +1,15 @@
1
+ module GirFFI
2
+ module FFIExt
3
+ module Pointer
4
+ def to_ptr
5
+ self
6
+ end
7
+
8
+ def to_value
9
+ self
10
+ end
11
+ end
12
+ end
13
+ end
14
+
15
+ FFI::Pointer.send :include, GirFFI::FFIExt::Pointer
@@ -8,11 +8,7 @@ module GirFFI
8
8
  return from_utf8_array ary if type == :utf8
9
9
  return from_interface_pointer_array ary if type == :interface_pointer
10
10
 
11
- ffi_type = TypeMap.map_basic_type type
12
- block = ArgHelper.allocate_array_of_type ffi_type, ary.length
13
- block.send "put_array_of_#{ffi_type}", 0, ary
14
-
15
- self.new block
11
+ return from_basic_type_array type, ary
16
12
  end
17
13
 
18
14
  def self.from type, val
@@ -48,6 +44,15 @@ module GirFFI
48
44
  ptr = AllocationHelper.safe_malloc(len + 1).write_string(str).put_char(len, 0)
49
45
  self.new ptr
50
46
  end
47
+
48
+ def from_basic_type_array type, ary
49
+ ffi_type = TypeMap.map_basic_type type
50
+ block = ArgHelper.allocate_array_of_type ffi_type, ary.length
51
+ block.send "put_array_of_#{ffi_type}", 0, ary
52
+
53
+ self.new block
54
+ end
55
+
51
56
  end
52
57
  end
53
58
  end
@@ -0,0 +1,15 @@
1
+ require 'gir_ffi/info_ext/i_type_info'
2
+
3
+ module GirFFI
4
+ module InfoExt
5
+ module IFieldInfo
6
+ def layout_specification
7
+ [ name.to_sym,
8
+ field_type.layout_specification_type,
9
+ offset ]
10
+ end
11
+ end
12
+ end
13
+ end
14
+
15
+ GObjectIntrospection::IFieldInfo.send :include, GirFFI::InfoExt::IFieldInfo
@@ -0,0 +1,26 @@
1
+ require 'gir_ffi/builder_helper'
2
+
3
+ module GirFFI
4
+ module InfoExt
5
+ module ITypeInfo
6
+ include BuilderHelper
7
+
8
+ def layout_specification_type
9
+ ffitype = GirFFI::Builder.itypeinfo_to_ffitype self
10
+ case ffitype
11
+ when Class
12
+ ffitype.const_get :Struct
13
+ when :bool
14
+ :int
15
+ when :array
16
+ subtype = param_type(0).layout_specification_type
17
+ [subtype, array_fixed_size]
18
+ else
19
+ ffitype
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ GObjectIntrospection::ITypeInfo.send :include, GirFFI::InfoExt::ITypeInfo
@@ -0,0 +1,18 @@
1
+ module GirFFI
2
+ # Generates method stubs that will replace themselves with the real
3
+ # method upon being called.
4
+ class MethodStubber
5
+ def initialize method_info
6
+ @info = method_info
7
+ end
8
+
9
+ def method_stub
10
+ symbol = @info.name
11
+ "
12
+ def #{@info.method? ? '' : 'self.'}#{symbol} *args, &block
13
+ setup_and_call :#{symbol}, *args, &block
14
+ end
15
+ "
16
+ end
17
+ end
18
+ end
@@ -4,6 +4,7 @@ module GirFFI
4
4
  gtype_type = "uint#{sz}".to_sym
5
5
 
6
6
  TAG_TYPE_MAP = {
7
+ #FIXME: Pick one: GType or gtype.
7
8
  :GType => :size_t,
8
9
  :gtype => gtype_type,
9
10
  :gboolean => :bool,
@@ -1,4 +1,6 @@
1
1
  module GirFFI
2
+ # Generates a sequence of unique variable names used in generating
3
+ # function definitions.
2
4
  class VariableNameGenerator
3
5
  def initialize
4
6
  @varno = 0
@@ -1,4 +1,4 @@
1
1
  module GirFFI
2
- VERSION = "0.2.2"
2
+ VERSION = "0.2.3"
3
3
  end
4
4
 
data/test/builder_test.rb CHANGED
@@ -64,7 +64,7 @@ class BuilderTest < MiniTest::Spec
64
64
  end
65
65
 
66
66
  should "create a Gtk::Window#to_ptr method" do
67
- assert Gtk::Window.instance_methods.map(&:to_sym).include? :to_ptr
67
+ assert Gtk::Window.public_method_defined? :to_ptr
68
68
  end
69
69
 
70
70
  after do
@@ -126,7 +126,7 @@ class BuilderTest < MiniTest::Spec
126
126
  end
127
127
 
128
128
  GirFFI::Builder.send :attach_ffi_function, libmod, @go
129
- assert libmod.public_methods.map(&:to_sym).include? :gtk_main
129
+ assert_defines_singleton_method libmod, :gtk_main
130
130
  end
131
131
  end
132
132
 
@@ -269,9 +269,10 @@ class BuilderTest < MiniTest::Spec
269
269
  GirFFI::Builder.build_module 'Regress'
270
270
  end
271
271
 
272
- should "have a method_missing method" do
273
- ms = (Regress.public_methods - Module.public_methods).map(&:to_sym)
274
- assert ms.include? :method_missing
272
+ should "autocreate singleton methods" do
273
+ refute_defines_singleton_method Regress, :test_uint
274
+ Regress.test_uint 31
275
+ assert_defines_singleton_method Regress, :test_uint
275
276
  end
276
277
 
277
278
  should "autocreate the TestObj class" do
@@ -32,12 +32,22 @@ describe GLib::Array do
32
32
 
33
33
  assert_equal [1, 2, 3], a
34
34
  end
35
+ end
36
+
37
+ describe "::wrap" do
38
+ it "wraps a pointer, taking the element type as the first argument" do
39
+ arr = GLib::Array.new :gint32
40
+ arr.append_vals [1, 2, 3]
41
+ arr2 = GLib::Array.wrap :gint32, arr.to_ptr
42
+ assert_equal arr.to_a, arr2.to_a
43
+ end
35
44
 
36
- it "returns an enumerator if no block is given" do
37
- en = @arr.each
38
- assert_equal 1, en.next
39
- assert_equal 2, en.next
40
- assert_equal 3, en.next
45
+ it "raises an error if the element sizes don't match" do
46
+ arr = GLib::Array.new :gint32
47
+ arr.append_vals [1, 2, 3]
48
+ assert_raises RuntimeError do
49
+ GLib::Array.wrap :gint8, arr.to_ptr
50
+ end
41
51
  end
42
52
  end
43
53
 
@@ -50,5 +60,30 @@ describe GLib::Array do
50
60
  arr.append_vals [1, 2, 3]
51
61
  assert_equal [1, 2, 3], arr.to_a
52
62
  end
63
+
64
+ describe "::from" do
65
+ it "creates a GArray from a Ruby array" do
66
+ arr = GLib::Array.from :gint32, [3, 2, 1]
67
+ assert_equal [3, 2, 1], arr.to_a
68
+ end
69
+
70
+ it "return its argument if given a GArray" do
71
+ arr = GLib::Array.new :gint32
72
+ arr.append_vals [3, 2, 1]
73
+ arr2 = GLib::Array.from :foo, arr
74
+ assert_equal arr, arr2
75
+ end
76
+
77
+ it "wraps its argument if given a pointer" do
78
+ arr = GLib::Array.new :gint32
79
+ arr.append_vals [3, 2, 1]
80
+ pointer = arr.to_ptr
81
+ assert_instance_of FFI::Pointer, pointer
82
+ arr2 = GLib::Array.from :gint32, pointer
83
+ assert_instance_of GLib::Array, arr2
84
+ refute_equal arr, arr2
85
+ assert_equal arr.to_a, arr2.to_a
86
+ end
87
+ end
53
88
  end
54
89
 
@@ -9,16 +9,40 @@ describe GLib::HashTable do
9
9
 
10
10
  describe "::from_hash" do
11
11
  it "creates a GHashTable from a Ruby array" do
12
- hsh = GLib::HashTable.from_hash :utf8, :gint32,
12
+ hsh = GLib::HashTable.from_hash [:utf8, :gint32],
13
13
  {"foo" => 23, "bar" => 32}
14
14
  assert_equal({"foo" => 23, "bar" => 32}, hsh.to_hash)
15
15
  end
16
16
 
17
17
  it "return its argument if given a GHashTable" do
18
- hsh = GLib::HashTable.from_hash :utf8, :gint32, {"foo" => 23, "bar" => 32}
19
- hsh2 = GLib::HashTable.from_hash :utf8, :gint32, hsh
18
+ hsh = GLib::HashTable.from_hash [:utf8, :gint32], {"foo" => 23, "bar" => 32}
19
+ hsh2 = GLib::HashTable.from_hash [:utf8, :gint32], hsh
20
20
  assert_equal hsh, hsh2
21
21
  end
22
22
  end
23
+
24
+ describe "::from" do
25
+ it "creates a GHashTable from a Ruby array" do
26
+ hsh = GLib::HashTable.from [:utf8, :gint32],
27
+ {"foo" => 23, "bar" => 32}
28
+ assert_equal({"foo" => 23, "bar" => 32}, hsh.to_hash)
29
+ end
30
+
31
+ it "return its argument if given a GHashTable" do
32
+ hsh = GLib::HashTable.from [:utf8, :gint32], {"foo" => 23, "bar" => 32}
33
+ hsh2 = GLib::HashTable.from [:utf8, :gint32], hsh
34
+ assert_equal hsh, hsh2
35
+ end
36
+
37
+ it "wraps its argument if given a pointer" do
38
+ hsh = GLib::HashTable.from [:utf8, :gint32], {"foo" => 23, "bar" => 32}
39
+ pointer = hsh.to_ptr
40
+ assert_instance_of FFI::Pointer, pointer
41
+ hsh2 = GLib::HashTable.from [:utf8, :gint32], pointer
42
+ assert_instance_of GLib::HashTable, hsh2
43
+ refute_equal hsh, hsh2
44
+ assert_equal hsh.to_hash, hsh2.to_hash
45
+ end
46
+ end
23
47
  end
24
48
 
@@ -43,4 +43,27 @@ describe GLib::List do
43
43
  assert_equal lst, lst2
44
44
  end
45
45
  end
46
+
47
+ describe "::from" do
48
+ it "creates a GList from a Ruby array" do
49
+ lst = GLib::List.from :gint32, [3, 2, 1]
50
+ assert_equal [3, 2, 1], lst.to_a
51
+ end
52
+
53
+ it "return its argument if given a GList" do
54
+ lst = GLib::List.from :gint32, [3, 2, 1]
55
+ lst2 = GLib::List.from :gint32, lst
56
+ assert_equal lst, lst2
57
+ end
58
+
59
+ it "wraps its argument if given a pointer" do
60
+ lst = GLib::List.from :gint32, [3, 2, 1]
61
+ pointer = lst.to_ptr
62
+ assert_instance_of FFI::Pointer, pointer
63
+ lst2 = GLib::List.from :gint32, pointer
64
+ assert_instance_of GLib::List, lst2
65
+ refute_equal lst, lst2
66
+ assert_equal lst.to_a, lst2.to_a
67
+ end
68
+ end
46
69
  end
@@ -0,0 +1,41 @@
1
+ require File.expand_path('../gir_ffi_test_helper.rb', File.dirname(__FILE__))
2
+
3
+ require 'ffi-glib/strv'
4
+
5
+ describe GLib::Strv do
6
+ it "wraps a pointer" do
7
+ strv = GLib::Strv.new :some_pointer
8
+ assert_equal :some_pointer, strv.to_ptr
9
+ end
10
+
11
+ describe "::wrap" do
12
+ it "takes a pointer and returns a GLib::Strv wrapping it" do
13
+ strv = GLib::Strv.wrap :some_pointer
14
+ assert_instance_of GLib::Strv, strv
15
+ assert_equal :some_pointer, strv.to_ptr
16
+ end
17
+ end
18
+
19
+ describe "#each" do
20
+ it "yields each string element" do
21
+ ptr = GirFFI::InPointer.from_array :utf8, ["one", "two", "three"]
22
+ strv = GLib::Strv.new ptr
23
+ arr = []
24
+ strv.each do |str|
25
+ arr << str
26
+ end
27
+ assert_equal ["one", "two", "three"], arr
28
+ end
29
+
30
+ it "yields zero times for a Strv wrapping a null pointer" do
31
+ strv = GLib::Strv.new FFI::Pointer.new(0)
32
+ strv.each do |str|
33
+ flunk
34
+ end
35
+ end
36
+ end
37
+
38
+ it "includes Enumerable" do
39
+ GLib::Strv.must_include Enumerable
40
+ end
41
+ end