gir_ffi 0.2.2 → 0.2.3

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