ffi 1.0.9 → 1.0.10

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of ffi might be problematic. Click here for more details.

Files changed (56) hide show
  1. data/Rakefile +4 -4
  2. data/ext/ffi_c/AbstractMemory.c +367 -14
  3. data/ext/ffi_c/AbstractMemory.h +4 -0
  4. data/ext/ffi_c/ArrayType.c +28 -0
  5. data/ext/ffi_c/Buffer.c +101 -25
  6. data/ext/ffi_c/Call.c +8 -5
  7. data/ext/ffi_c/ClosurePool.c +9 -8
  8. data/ext/ffi_c/DataConverter.c +29 -0
  9. data/ext/ffi_c/DynamicLibrary.c +64 -1
  10. data/ext/ffi_c/Function.c +111 -10
  11. data/ext/ffi_c/FunctionInfo.c +13 -1
  12. data/ext/ffi_c/LastError.c +16 -0
  13. data/ext/ffi_c/MappedType.c +22 -0
  14. data/ext/ffi_c/MemoryPointer.c +11 -1
  15. data/ext/ffi_c/MethodHandle.c +18 -11
  16. data/ext/ffi_c/Platform.c +9 -3
  17. data/ext/ffi_c/Pointer.c +98 -0
  18. data/ext/ffi_c/Struct.c +4 -4
  19. data/ext/ffi_c/Struct.h +2 -1
  20. data/ext/ffi_c/StructLayout.c +2 -2
  21. data/ext/ffi_c/Thread.c +124 -1
  22. data/ext/ffi_c/Type.c +108 -17
  23. data/ext/ffi_c/Types.c +9 -2
  24. data/ext/ffi_c/Variadic.c +5 -4
  25. data/ext/ffi_c/compat.h +8 -0
  26. data/ext/ffi_c/endian.h +7 -1
  27. data/ext/ffi_c/extconf.rb +46 -35
  28. data/ext/ffi_c/ffi.c +5 -0
  29. data/ext/ffi_c/libffi.darwin.mk +15 -15
  30. data/ext/ffi_c/libffi.gnu.mk +3 -3
  31. data/ext/ffi_c/libffi.mk +4 -4
  32. data/lib/ffi.rb +13 -9
  33. data/lib/ffi/autopointer.rb +88 -26
  34. data/lib/ffi/enum.rb +42 -0
  35. data/lib/ffi/errno.rb +6 -1
  36. data/lib/ffi/ffi.rb +1 -0
  37. data/lib/ffi/io.rb +13 -2
  38. data/lib/ffi/library.rb +212 -19
  39. data/lib/ffi/memorypointer.rb +1 -33
  40. data/lib/ffi/platform.rb +23 -7
  41. data/lib/ffi/platform/i386-freebsd/types.conf +152 -0
  42. data/lib/ffi/platform/i386-netbsd/types.conf +126 -0
  43. data/lib/ffi/platform/x86_64-freebsd/types.conf +126 -0
  44. data/lib/ffi/platform/x86_64-netbsd/types.conf +126 -0
  45. data/lib/ffi/pointer.rb +44 -0
  46. data/lib/ffi/struct.rb +1 -1
  47. data/lib/ffi/struct_layout_builder.rb +2 -1
  48. data/lib/ffi/tools/const_generator.rb +72 -17
  49. data/lib/ffi/types.rb +21 -1
  50. data/spec/ffi/rbx/memory_pointer_spec.rb +4 -2
  51. data/spec/ffi/struct_spec.rb +10 -0
  52. data/spec/ffi/typedef_spec.rb +11 -0
  53. data/tasks/extension.rake +0 -1
  54. data/tasks/gem.rake +0 -1
  55. data/tasks/yard.rake +11 -0
  56. metadata +15 -8
@@ -0,0 +1,126 @@
1
+ rbx.platform.typedef.__int8_t = char
2
+ rbx.platform.typedef.__uint8_t = uchar
3
+ rbx.platform.typedef.__int16_t = short
4
+ rbx.platform.typedef.__uint16_t = ushort
5
+ rbx.platform.typedef.__int32_t = int
6
+ rbx.platform.typedef.__uint32_t = uint
7
+ rbx.platform.typedef.__int64_t = long_long
8
+ rbx.platform.typedef.__uint64_t = ulong_long
9
+ rbx.platform.typedef.__int_least8_t = char
10
+ rbx.platform.typedef.__uint_least8_t = uchar
11
+ rbx.platform.typedef.__int_least16_t = short
12
+ rbx.platform.typedef.__uint_least16_t = ushort
13
+ rbx.platform.typedef.__int_least32_t = int
14
+ rbx.platform.typedef.__uint_least32_t = uint
15
+ rbx.platform.typedef.__int_least64_t = long_long
16
+ rbx.platform.typedef.__uint_least64_t = ulong_long
17
+ rbx.platform.typedef.__int_fast8_t = int
18
+ rbx.platform.typedef.__uint_fast8_t = uint
19
+ rbx.platform.typedef.__int_fast16_t = int
20
+ rbx.platform.typedef.__uint_fast16_t = uint
21
+ rbx.platform.typedef.__int_fast32_t = int
22
+ rbx.platform.typedef.__uint_fast32_t = uint
23
+ rbx.platform.typedef.__int_fast64_t = long_long
24
+ rbx.platform.typedef.__uint_fast64_t = ulong_long
25
+ rbx.platform.typedef.__intptr_t = long
26
+ rbx.platform.typedef.__uintptr_t = ulong
27
+ rbx.platform.typedef.__intmax_t = long_long
28
+ rbx.platform.typedef.__uintmax_t = ulong_long
29
+ rbx.platform.typedef.__register_t = int
30
+ rbx.platform.typedef.__vaddr_t = ulong
31
+ rbx.platform.typedef.__paddr_t = ulong
32
+ rbx.platform.typedef.__vsize_t = ulong
33
+ rbx.platform.typedef.__psize_t = ulong
34
+ rbx.platform.typedef.__clock_t = int
35
+ rbx.platform.typedef.__clockid_t = int
36
+ rbx.platform.typedef.__off_t = long_long
37
+ rbx.platform.typedef.__ptrdiff_t = long
38
+ rbx.platform.typedef.__size_t = ulong
39
+ rbx.platform.typedef.__ssize_t = long
40
+ rbx.platform.typedef.__time_t = int
41
+ rbx.platform.typedef.__timer_t = int
42
+ rbx.platform.typedef.__wchar_t = int
43
+ rbx.platform.typedef.__wint_t = int
44
+ rbx.platform.typedef.__rune_t = int
45
+ rbx.platform.typedef.__wctrans_t = pointer
46
+ rbx.platform.typedef.__wctype_t = pointer
47
+ rbx.platform.typedef.__cpuid_t = ulong
48
+ rbx.platform.typedef.__dev_t = int
49
+ rbx.platform.typedef.__fixpt_t = uint
50
+ rbx.platform.typedef.__gid_t = uint
51
+ rbx.platform.typedef.__id_t = uint
52
+ rbx.platform.typedef.__in_addr_t = uint
53
+ rbx.platform.typedef.__in_port_t = ushort
54
+ rbx.platform.typedef.__ino_t = uint
55
+ rbx.platform.typedef.__key_t = long
56
+ rbx.platform.typedef.__mode_t = uint
57
+ rbx.platform.typedef.__nlink_t = uint
58
+ rbx.platform.typedef.__pid_t = int
59
+ rbx.platform.typedef.__rlim_t = ulong_long
60
+ rbx.platform.typedef.__sa_family_t = uchar
61
+ rbx.platform.typedef.__segsz_t = int
62
+ rbx.platform.typedef.__socklen_t = uint
63
+ rbx.platform.typedef.__swblk_t = int
64
+ rbx.platform.typedef.__uid_t = uint
65
+ rbx.platform.typedef.__useconds_t = uint
66
+ rbx.platform.typedef.__suseconds_t = int
67
+ rbx.platform.typedef.u_char = uchar
68
+ rbx.platform.typedef.u_short = ushort
69
+ rbx.platform.typedef.u_int = uint
70
+ rbx.platform.typedef.u_long = ulong
71
+ rbx.platform.typedef.unchar = uchar
72
+ rbx.platform.typedef.ushort = ushort
73
+ rbx.platform.typedef.uint = uint
74
+ rbx.platform.typedef.ulong = ulong
75
+ rbx.platform.typedef.cpuid_t = ulong
76
+ rbx.platform.typedef.register_t = int
77
+ rbx.platform.typedef.int8_t = char
78
+ rbx.platform.typedef.uint8_t = uchar
79
+ rbx.platform.typedef.int16_t = short
80
+ rbx.platform.typedef.uint16_t = ushort
81
+ rbx.platform.typedef.int32_t = int
82
+ rbx.platform.typedef.uint32_t = uint
83
+ rbx.platform.typedef.int64_t = long_long
84
+ rbx.platform.typedef.uint64_t = ulong_long
85
+ rbx.platform.typedef.u_int8_t = uchar
86
+ rbx.platform.typedef.u_int16_t = ushort
87
+ rbx.platform.typedef.u_int32_t = uint
88
+ rbx.platform.typedef.u_int64_t = ulong_long
89
+ rbx.platform.typedef.quad_t = long_long
90
+ rbx.platform.typedef.u_quad_t = ulong_long
91
+ rbx.platform.typedef.qaddr_t = pointer
92
+ rbx.platform.typedef.vaddr_t = ulong
93
+ rbx.platform.typedef.paddr_t = ulong
94
+ rbx.platform.typedef.vsize_t = ulong
95
+ rbx.platform.typedef.psize_t = ulong
96
+ rbx.platform.typedef.caddr_t = string
97
+ rbx.platform.typedef.daddr_t = int
98
+ rbx.platform.typedef.daddr32_t = int
99
+ rbx.platform.typedef.daddr64_t = long_long
100
+ rbx.platform.typedef.dev_t = int
101
+ rbx.platform.typedef.fixpt_t = uint
102
+ rbx.platform.typedef.gid_t = uint
103
+ rbx.platform.typedef.id_t = uint
104
+ rbx.platform.typedef.ino_t = uint
105
+ rbx.platform.typedef.key_t = long
106
+ rbx.platform.typedef.mode_t = uint
107
+ rbx.platform.typedef.nlink_t = uint
108
+ rbx.platform.typedef.pid_t = int
109
+ rbx.platform.typedef.rlim_t = ulong_long
110
+ rbx.platform.typedef.segsz_t = int
111
+ rbx.platform.typedef.swblk_t = int
112
+ rbx.platform.typedef.uid_t = uint
113
+ rbx.platform.typedef.useconds_t = uint
114
+ rbx.platform.typedef.suseconds_t = int
115
+ rbx.platform.typedef.in_addr_t = uint
116
+ rbx.platform.typedef.in_port_t = ushort
117
+ rbx.platform.typedef.sa_family_t = uchar
118
+ rbx.platform.typedef.socklen_t = uint
119
+ rbx.platform.typedef.clock_t = int
120
+ rbx.platform.typedef.clockid_t = int
121
+ rbx.platform.typedef.size_t = ulong
122
+ rbx.platform.typedef.ssize_t = long
123
+ rbx.platform.typedef.time_t = int
124
+ rbx.platform.typedef.timer_t = int
125
+ rbx.platform.typedef.off_t = long_long
126
+ rbx.platform.typedef.__fd_mask = int
@@ -21,13 +21,20 @@
21
21
  require 'ffi/platform'
22
22
  module FFI
23
23
  class Pointer
24
+
25
+ # Pointer size
24
26
  SIZE = Platform::ADDRESS_SIZE / 8
25
27
 
26
28
  # Return the size of a pointer on the current platform, in bytes
29
+ # @return [Numeric]
27
30
  def self.size
28
31
  SIZE
29
32
  end
30
33
 
34
+ # @param [nil,Numeric] len length of string to return
35
+ # @return [String]
36
+ # Read pointer's contents as a string, or the first +len+ bytes of the
37
+ # equivalent string if +len+ is not +nil+.
31
38
  def read_string(len=nil)
32
39
  if len
33
40
  get_bytes(0, len)
@@ -36,24 +43,54 @@ module FFI
36
43
  end
37
44
  end
38
45
 
46
+ # @param [Numeric] len length of string to return
47
+ # @return [String]
48
+ # Read the first +len+ bytes of pointer's contents as a string.
49
+ #
50
+ # Same as:
51
+ # ptr.read_string(len) # with len not nil
39
52
  def read_string_length(len)
40
53
  get_bytes(0, len)
41
54
  end
42
55
 
56
+ # @return [String]
57
+ # Read pointer's contents as a string.
58
+ #
59
+ # Same as:
60
+ # ptr.read_string # with no len
43
61
  def read_string_to_null
44
62
  get_string(0)
45
63
  end
46
64
 
65
+ # @param [String] str string to write
66
+ # @param [Numeric] len length of string to return
67
+ # @return [self]
68
+ # Write +len+ first bytes of +str+ in pointer's contents.
69
+ #
70
+ # Same as:
71
+ # ptr.write_string(str, len) # with len not nil
47
72
  def write_string_length(str, len)
48
73
  put_bytes(0, str, 0, len)
49
74
  end
50
75
 
76
+ # @param [String] str string to write
77
+ # @param [Numeric] len length of string to return
78
+ # @return [self]
79
+ # Write +str+ in pointer's contents, or first +len+ bytes if
80
+ # +len+ is not +nil+.
51
81
  def write_string(str, len=nil)
52
82
  len = str.bytesize unless len
53
83
  # Write the string data without NUL termination
54
84
  put_bytes(0, str, 0, len)
55
85
  end
56
86
 
87
+ # @param [Type] type type of data to read from pointer's contents
88
+ # @param [Symbol] reader method to send to +self+ to read +type+
89
+ # @param [Numeric] length
90
+ # @return [Array]
91
+ # Read an array of +type+ of length +length+.
92
+ # @example
93
+ # ptr.write_array_of_type(TYPE_UINT8, :get_uint8, 4) # -> [1, 2, 3, 4]
57
94
  def read_array_of_type(type, reader, length)
58
95
  ary = []
59
96
  size = FFI.type_size(type)
@@ -65,6 +102,13 @@ module FFI
65
102
  ary
66
103
  end
67
104
 
105
+ # @param [Type] type type of data to write to pointer's contents
106
+ # @param [Symbol] writer method to send to +self+ to write +type+
107
+ # @param [Array] ary
108
+ # @return [self]
109
+ # Write +ary+ in pointer's contents as +type+.
110
+ # @example
111
+ # ptr.write_array_of_type(TYPE_UINT8, :put_uint8, [1, 2, 3 ,4])
68
112
  def write_array_of_type(type, writer, ary)
69
113
  size = FFI.type_size(type)
70
114
  tmp = self
@@ -222,7 +222,7 @@ module FFI
222
222
  def aligned(alignment = 1)
223
223
  @min_alignment = alignment
224
224
  end
225
- alias_method :align, :aligned
225
+ alias :align :aligned
226
226
 
227
227
  def enclosing_module
228
228
  begin
@@ -71,6 +71,7 @@ module FFI
71
71
  Type::UINT64,
72
72
  Type::FLOAT32,
73
73
  Type::FLOAT64,
74
+ Type::BOOL,
74
75
  ]
75
76
 
76
77
  def add(name, type, offset = nil)
@@ -155,4 +156,4 @@ module FFI
155
156
  end
156
157
  end
157
158
 
158
- end
159
+ end
@@ -3,23 +3,38 @@ require 'open3'
3
3
 
4
4
  module FFI
5
5
 
6
- ##
7
6
  # ConstGenerator turns C constants into ruby values.
8
-
7
+ #
8
+ # @example a simple example for stdio
9
+ # cg = FFI::ConstGenerator.new('stdio') do |gen|
10
+ # gen.const(:SEEK_SET)
11
+ # gen.const('SEEK_CUR')
12
+ # gen.const('seek_end') # this constant does not exist
13
+ # end # #calculate called automatically at the end of the block
14
+ #
15
+ # cg['SEEK_SET'] # => 0
16
+ # cg['SEEK_CUR'] # => 1
17
+ # cg['seek_end'] # => nil
18
+ # cg.to_ruby # => "SEEK_SET = 0\nSEEK_CUR = 1\n# seek_end not available"
9
19
  class ConstGenerator
10
20
  @options = {}
11
21
  attr_reader :constants
12
22
 
13
- ##
14
23
  # Creates a new constant generator that uses +prefix+ as a name, and an
15
24
  # options hash.
16
25
  #
17
- # The only option is :required, which if set to true raises an error if a
26
+ # The only option is +:required+, which if set to +true+ raises an error if a
18
27
  # constant you have requested was not found.
19
- #
20
- # When passed a block, #calculate is automatically called at the end of
21
- # the block, otherwise you must call it yourself.
22
-
28
+ #
29
+ # @param [#to_s] prefix
30
+ # @param [Hash] options
31
+ # @return
32
+ # @option options [Boolean] :required
33
+ # @overload initialize(prefix, options)
34
+ # @overload initialize(prefix, options) { |gen| ... }
35
+ # @yieldparam [ConstGenerator] gen new generator is passed to the block
36
+ # When passed a block, {#calculate} is automatically called at the end of
37
+ # the block, otherwise you must call it yourself.
23
38
  def initialize(prefix = nil, options = {})
24
39
  @includes = []
25
40
  @constants = {}
@@ -33,23 +48,40 @@ module FFI
33
48
  calculate self.class.options.merge(options)
34
49
  end
35
50
  end
51
+ # Set class options
52
+ # These options are merged with {#initialize} options when it is called with a block.
53
+ # @param [Hash] options
54
+ # @return [Hash] class options
36
55
  def self.options=(options)
37
56
  @options = options
38
57
  end
58
+ # Get class options.
59
+ # @return [Hash] class options
39
60
  def self.options
40
61
  @options
41
62
  end
63
+ # @param [String] name
64
+ # @return constant value
65
+ # Access a constant by name.
42
66
  def [](name)
43
67
  @constants[name].value
44
68
  end
45
69
 
46
- ##
47
- # Request the value for C constant +name+. +format+ is a printf format
48
- # string to print the value out, and +cast+ is a C cast for the value.
49
- # +ruby_name+ allows you to give the constant an alternate ruby name for
50
- # #to_ruby. +converter+ or +converter_proc+ allow you to convert the
51
- # value from a string to the appropriate type for #to_ruby.
52
-
70
+ # Request the value for C constant +name+.
71
+ #
72
+ # @param [#to_s] name C constant name
73
+ # @param [String] format a printf format string to print the value out
74
+ # @param [String] cast a C cast for the value
75
+ # @param ruby_name alternate ruby name for {#to_ruby}
76
+ #
77
+ # @overload const(name, format=nil, cast='', ruby_name=nil, converter=nil)
78
+ # +converter+ is a Method or a Proc.
79
+ # @param [#call] converter convert the value from a string to the appropriate
80
+ # type for {#to_ruby}.
81
+ # @overload const(name, format=nil, cast='', ruby_name=nil) { |value| ... }
82
+ # Use a converter block. This block convert the value from a string to the
83
+ # appropriate type for {#to_ruby}.
84
+ # @yieldparam value constant value
53
85
  def const(name, format = nil, cast = '', ruby_name = nil, converter = nil,
54
86
  &converter_proc)
55
87
  format ||= '%d'
@@ -66,6 +98,11 @@ module FFI
66
98
  return const
67
99
  end
68
100
 
101
+ # Calculate constants values.
102
+ # @param [Hash] options
103
+ # @option options [String] :cppflags flags for C compiler
104
+ # @return [nil]
105
+ # @raise if a constant is missing and +:required+ was set to +true+ (see {#initialize})
69
106
  def calculate(options = {})
70
107
  binary = File.join Dir.tmpdir, "rb_const_gen_bin_#{Process.pid}"
71
108
 
@@ -115,6 +152,9 @@ module FFI
115
152
  end
116
153
  end
117
154
 
155
+ # Dump constants to +io+.
156
+ # @param [#puts] io
157
+ # @return [nil]
118
158
  def dump_constants(io)
119
159
  @constants.each do |name, constant|
120
160
  name = [@prefix, name].join '.' if @prefix
@@ -122,10 +162,9 @@ module FFI
122
162
  end
123
163
  end
124
164
 
125
- ##
126
165
  # Outputs values for discovered constants. If the constant's value was
127
166
  # not discovered it is not omitted.
128
-
167
+ # @return [String]
129
168
  def to_ruby
130
169
  @constants.sort_by { |name,| name }.map do |name, constant|
131
170
  if constant.value.nil? then
@@ -136,17 +175,27 @@ module FFI
136
175
  end.join "\n"
137
176
  end
138
177
 
178
+ # Add a C include file to calculate constants from.
179
+ # @param [String] i include file
180
+ # @return [Array<String>] array of include files (stdio.h is omitted)
139
181
  def include(i)
140
182
  @includes << i
141
183
  end
142
184
 
143
185
  end
144
186
 
187
+ # This class hold constants for {ConstGenerator}
145
188
  class ConstGenerator::Constant
146
189
 
147
190
  attr_reader :name, :format, :cast
148
191
  attr_accessor :value
149
192
 
193
+ # @param [#to_s] name
194
+ # @param [String] format a printf format string to print the value out
195
+ # @param [String] cast a C cast for the value
196
+ # @param ruby_name alternate ruby name for {#to_ruby}
197
+ # @param [#call] converter convert the value from a string to the appropriate
198
+ # type for {#to_ruby}.
150
199
  def initialize(name, format, cast, ruby_name = nil, converter=nil)
151
200
  @name = name
152
201
  @format = format
@@ -156,6 +205,8 @@ module FFI
156
205
  @value = nil
157
206
  end
158
207
 
208
+ # Return constant value (converted if a +converter+ was defined).
209
+ # @return constant value.
159
210
  def converted_value
160
211
  if @converter
161
212
  @converter.call(@value)
@@ -164,10 +215,14 @@ module FFI
164
215
  end
165
216
  end
166
217
 
218
+ # get constant ruby name
219
+ # @return [String]
167
220
  def ruby_name
168
221
  @ruby_name || @name
169
222
  end
170
223
 
224
+ # Get an evaluable string from constant.
225
+ # @return [String]
171
226
  def to_ruby
172
227
  "#{ruby_name} = #{converted_value}"
173
228
  end
@@ -17,17 +17,29 @@
17
17
  # version 3 along with this work. If not, see <http://www.gnu.org/licenses/>.
18
18
  #
19
19
 
20
+ # see {file:README}
20
21
  module FFI
21
22
 
23
+ # @param [Type, DataConverter, Symbol] old type definition used by {FFI.find_type}
24
+ # @param [Symbol] add new type definition's name to add
25
+ # @return [Type]
26
+ # Add a definition type to type definitions.
22
27
  def self.typedef(old, add)
23
28
  TypeDefs[add] = self.find_type(old)
24
29
  end
25
30
 
31
+ # (see FFI.typedef)
26
32
  def self.add_typedef(old, add)
27
33
  typedef old, add
28
34
  end
29
35
 
30
36
 
37
+ # @param [Type, DataConverter, Symbol] name
38
+ # @param [Hash] type_map if nil, {FFI::TypeDefs} is used
39
+ # @return [Type]
40
+ # Find a type in +type_map+ ({FFI::TypeDefs}, by default) from
41
+ # a type objet, a type name (symbol). If +name+ is a {DataConverter},
42
+ # a new {Type::Mapped} is created.
31
43
  def self.find_type(name, type_map = nil)
32
44
  if name.is_a?(Type)
33
45
  name
@@ -46,6 +58,7 @@ module FFI
46
58
  end
47
59
  end
48
60
 
61
+ # List of type definitions
49
62
  TypeDefs.merge!({
50
63
  # The C void type; only useful for function return types
51
64
  :void => Type::VOID,
@@ -120,11 +133,15 @@ module FFI
120
133
  :varargs => Type::VARARGS,
121
134
  })
122
135
 
123
- # Returns a [ String, Pointer ] tuple so the C memory for the string can be freed
136
+
124
137
  class StrPtrConverter
125
138
  extend DataConverter
126
139
  native_type Type::POINTER
127
140
 
141
+ # @param [Pointer] val
142
+ # @param [] ctx
143
+ # @return [Array(String, Pointer)]
144
+ # Returns a [ String, Pointer ] tuple so the C memory for the string can be freed
128
145
  def self.from_native(val, ctx)
129
146
  [ val.null? ? nil : val.get_string(0), val ]
130
147
  end
@@ -133,6 +150,9 @@ module FFI
133
150
 
134
151
  typedef(StrPtrConverter, :strptr)
135
152
 
153
+ # @param type +type+ is an instance of class accepted by {FFI.find_type}
154
+ # @return [Numeric]
155
+ # Get +type+ size, in bytes.
136
156
  def self.type_size(type)
137
157
  find_type(type).size
138
158
  end