ffi 0.6.3-x86-mingw32 → 1.0.1-x86-mingw32

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 (64) hide show
  1. data/History.txt +7 -0
  2. data/LICENSE +10 -21
  3. data/README.rdoc +1 -0
  4. data/Rakefile +4 -2
  5. data/ext/ffi_c/AbstractMemory.c +103 -38
  6. data/ext/ffi_c/AbstractMemory.h +15 -22
  7. data/ext/ffi_c/Buffer.c +61 -22
  8. data/ext/ffi_c/Call.c +52 -540
  9. data/ext/ffi_c/Call.h +1 -1
  10. data/ext/ffi_c/DataConverter.c +62 -0
  11. data/ext/ffi_c/DynamicLibrary.c +21 -1
  12. data/ext/ffi_c/Function.c +315 -30
  13. data/ext/ffi_c/MappedType.c +146 -0
  14. data/ext/ffi_c/MappedType.h +57 -0
  15. data/ext/ffi_c/MemoryPointer.c +12 -33
  16. data/ext/ffi_c/Platform.c +2 -0
  17. data/ext/ffi_c/Pointer.c +66 -28
  18. data/ext/ffi_c/Struct.c +19 -306
  19. data/ext/ffi_c/Struct.h +6 -0
  20. data/ext/ffi_c/StructByReference.c +150 -0
  21. data/ext/ffi_c/StructByReference.h +50 -0
  22. data/ext/ffi_c/StructLayout.c +25 -14
  23. data/ext/ffi_c/Type.c +39 -68
  24. data/ext/ffi_c/Type.h +12 -22
  25. data/ext/ffi_c/Types.c +20 -5
  26. data/ext/ffi_c/Types.h +7 -7
  27. data/ext/ffi_c/Variadic.c +21 -17
  28. data/ext/ffi_c/extconf.rb +4 -0
  29. data/ext/ffi_c/ffi.c +8 -2
  30. data/ext/ffi_c/rbffi.h +1 -0
  31. data/lib/ffi/autopointer.rb +23 -22
  32. data/lib/ffi/enum.rb +36 -21
  33. data/lib/ffi/errno.rb +20 -0
  34. data/lib/ffi/ffi.rb +13 -80
  35. data/lib/ffi/io.rb +12 -20
  36. data/lib/ffi/library.rb +109 -92
  37. data/lib/ffi/managedstruct.rb +1 -1
  38. data/lib/ffi/memorypointer.rb +15 -21
  39. data/lib/ffi/platform.rb +24 -28
  40. data/lib/ffi/pointer.rb +14 -21
  41. data/lib/ffi/struct.rb +98 -49
  42. data/lib/ffi/struct_layout_builder.rb +158 -0
  43. data/lib/ffi/types.rb +99 -128
  44. data/lib/ffi/union.rb +20 -0
  45. data/lib/ffi/variadic.rb +33 -22
  46. data/lib/ffi_c.so +0 -0
  47. data/spec/ffi/async_callback_spec.rb +23 -0
  48. data/spec/ffi/callback_spec.rb +62 -0
  49. data/spec/ffi/custom_param_type.rb +31 -0
  50. data/spec/ffi/custom_type_spec.rb +73 -0
  51. data/spec/ffi/enum_spec.rb +19 -0
  52. data/spec/ffi/ffi_spec.rb +24 -0
  53. data/spec/ffi/pointer_spec.rb +15 -0
  54. data/spec/ffi/rbx/memory_pointer_spec.rb +7 -1
  55. data/spec/ffi/strptr_spec.rb +36 -0
  56. data/spec/ffi/struct_packed_spec.rb +46 -0
  57. data/spec/ffi/struct_spec.rb +19 -5
  58. data/spec/ffi/typedef_spec.rb +14 -0
  59. data/tasks/setup.rb +2 -1
  60. metadata +15 -6
  61. data/ext/ffi_c/AutoPointer.c +0 -60
  62. data/ext/ffi_c/AutoPointer.h +0 -18
  63. data/lib/1.8/ffi_c.so +0 -0
  64. data/lib/1.9/ffi_c.so +0 -0
@@ -1,179 +1,150 @@
1
1
  #
2
- # Copyright (C) 2008, 2009 Wayne Meissner
3
- # Copyright (C) 2009 Luc Heinrich
4
- # Copyright (c) 2007, 2008 Evan Phoenix
2
+ # Copyright (C) 2008-2010 Wayne Meissner
5
3
  # All rights reserved.
6
4
  #
7
- # Redistribution and use in source and binary forms, with or without
8
- # modification, are permitted provided that the following conditions are met:
5
+ # This file is part of ruby-ffi.
9
6
  #
10
- # * Redistributions of source code must retain the above copyright notice, this
11
- # list of conditions and the following disclaimer.
12
- # * Redistributions in binary form must reproduce the above copyright notice
13
- # this list of conditions and the following disclaimer in the documentation
14
- # and/or other materials provided with the distribution.
15
- # * Neither the name of the Evan Phoenix nor the names of its contributors
16
- # may be used to endorse or promote products derived from this software
17
- # without specific prior written permission.
7
+ # This code is free software: you can redistribute it and/or modify it under
8
+ # the terms of the GNU Lesser General Public License version 3 only, as
9
+ # published by the Free Software Foundation.
10
+ #
11
+ # This code is distributed in the hope that it will be useful, but WITHOUT
12
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
14
+ # version 3 for more details.
15
+ #
16
+ # You should have received a copy of the GNU Lesser General Public License
17
+ # version 3 along with this work. If not, see <http://www.gnu.org/licenses/>.
18
18
  #
19
- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
- # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
- # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
- # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
23
- # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
- # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
- # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
- # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
- # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
- # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
19
 
30
20
  module FFI
31
- # TypeDefs = Hash.new
32
- def self.add_typedef(current, add)
33
- if current.kind_of?(FFI::Type)
34
- code = current
35
- else
36
- code = TypeDefs[current]
37
- raise TypeError, "Unable to resolve type '#{current}'" unless code
38
- end
39
21
 
40
- TypeDefs[add] = code
22
+ def self.typedef(old, add)
23
+ TypeDefs[add] = self.find_type(old)
41
24
  end
42
- def self.find_type(name, type_map = nil)
43
- type_map = TypeDefs if type_map.nil?
44
- code = type_map[name]
45
- code = name if !code && name.kind_of?(FFI::Type)
46
- raise TypeError, "Unable to resolve type '#{name}'" unless code
47
- return code
48
- end
49
-
50
- # Converts a char
51
- add_typedef(NativeType::INT8, :char)
52
25
 
53
- # Converts an unsigned char
54
- add_typedef(NativeType::UINT8, :uchar)
55
-
56
- # Converts an 8 bit int
57
- add_typedef(NativeType::INT8, :int8)
26
+ def self.add_typedef(old, add)
27
+ typedef old, add
28
+ end
58
29
 
59
- # Converts an unsigned char
60
- add_typedef(NativeType::UINT8, :uint8)
61
30
 
62
- # Converts a short
63
- add_typedef(NativeType::INT16, :short)
31
+ def self.find_type(name, type_map = nil)
32
+ if name.is_a?(Type)
33
+ name
64
34
 
65
- # Converts an unsigned short
66
- add_typedef(NativeType::UINT16, :ushort)
35
+ elsif type_map && type_map.has_key?(name)
36
+ type_map[name]
67
37
 
68
- # Converts a 16bit int
69
- add_typedef(NativeType::INT16, :int16)
38
+ elsif TypeDefs.has_key?(name)
39
+ TypeDefs[name]
70
40
 
71
- # Converts an unsigned 16 bit int
72
- add_typedef(NativeType::UINT16, :uint16)
41
+ elsif name.is_a?(DataConverter)
42
+ (type_map || TypeDefs)[name] = Type::Mapped.new(name)
43
+
44
+ else
45
+ raise TypeError, "unable to resolve type '#{name}'"
46
+ end
47
+ end
73
48
 
74
- # Converts an int
75
- add_typedef(NativeType::INT32, :int)
49
+ TypeDefs.merge!({
50
+ # The C void type; only useful for function return types
51
+ :void => Type::VOID,
76
52
 
77
- # Converts an unsigned int
78
- add_typedef(NativeType::UINT32, :uint)
53
+ # C boolean type
54
+ :bool => Type::BOOL,
79
55
 
80
- # Converts a 32 bit int
81
- add_typedef(NativeType::INT32, :int32)
56
+ # C nul-terminated string
57
+ :string => Type::STRING,
82
58
 
83
- # Converts an unsigned 16 bit int
84
- add_typedef(NativeType::UINT32, :uint32)
59
+ # C signed char
60
+ :char => Type::CHAR,
61
+ # C unsigned char
62
+ :uchar => Type::UCHAR,
85
63
 
86
- # Converts a long
87
- add_typedef(NativeType::LONG, :long)
64
+ # C signed short
65
+ :short => Type::SHORT,
66
+ # C unsigned short
67
+ :ushort => Type::USHORT,
88
68
 
89
- # Converts an unsigned long
90
- add_typedef(NativeType::ULONG, :ulong)
69
+ # C signed int
70
+ :int => Type::INT,
71
+ # C unsigned int
72
+ :uint => Type::UINT,
91
73
 
92
- # Converts a 64 bit int
93
- add_typedef(NativeType::INT64, :int64)
74
+ # C signed long
75
+ :long => Type::LONG,
94
76
 
95
- # Converts an unsigned 64 bit int
96
- add_typedef(NativeType::UINT64, :uint64)
77
+ # C unsigned long
78
+ :ulong => Type::ULONG,
97
79
 
98
- # Converts a long long
99
- add_typedef(NativeType::INT64, :long_long)
80
+ # C signed long long integer
81
+ :long_long => Type::LONG_LONG,
100
82
 
101
- # Converts an unsigned long long
102
- add_typedef(NativeType::UINT64, :ulong_long)
83
+ # C unsigned long long integer
84
+ :ulong_long => Type::ULONG_LONG,
103
85
 
104
- # Converts a float
105
- add_typedef(NativeType::FLOAT32, :float)
86
+ # C single precision float
87
+ :float => Type::FLOAT,
106
88
 
107
- # Converts a double
108
- add_typedef(NativeType::FLOAT64, :double)
89
+ # C double precision float
90
+ :double => Type::DOUBLE,
109
91
 
110
- # Converts a pointer to opaque data
111
- add_typedef(NativeType::POINTER, :pointer)
92
+ # Native memory address
93
+ :pointer => Type::POINTER,
112
94
 
113
- # For when a function has no return value
114
- add_typedef(NativeType::VOID, :void)
95
+ # 8 bit signed integer
96
+ :int8 => Type::INT8,
97
+ # 8 bit unsigned integer
98
+ :uint8 => Type::UINT8,
115
99
 
116
- # Converts NUL-terminated C strings
117
- add_typedef(NativeType::STRING, :string)
100
+ # 16 bit signed integer
101
+ :int16 => Type::INT16,
102
+ # 16 bit unsigned integer
103
+ :uint16 => Type::UINT16,
118
104
 
119
- # Converts FFI::Buffer objects
120
- add_typedef(NativeType::BUFFER_IN, :buffer_in)
121
- add_typedef(NativeType::BUFFER_OUT, :buffer_out)
122
- add_typedef(NativeType::BUFFER_INOUT, :buffer_inout)
105
+ # 32 bit signed integer
106
+ :int32 => Type::INT32,
107
+ # 32 bit unsigned integer
108
+ :uint32 => Type::UINT32,
123
109
 
124
- add_typedef(NativeType::VARARGS, :varargs)
125
-
126
- add_typedef(NativeType::ENUM, :enum)
127
- add_typedef(NativeType::BOOL, :bool)
110
+ # 64 bit signed integer
111
+ :int64 => Type::INT64,
112
+ # 64 bit unsigned integer
113
+ :uint64 => Type::UINT64,
128
114
 
129
- # Use for a C struct with a char [] embedded inside.
130
- add_typedef(NativeType::CHAR_ARRAY, :char_array)
115
+ :buffer_in => Type::BUFFER_IN,
116
+ :buffer_out => Type::BUFFER_OUT,
117
+ :buffer_inout => Type::BUFFER_INOUT,
131
118
 
132
- TypeSizes = {
133
- 1 => :char,
134
- 2 => :short,
135
- 4 => :int,
136
- 8 => :long_long,
137
- }
138
- SizeTypes.merge!({
139
- NativeType::INT8 => 1,
140
- NativeType::UINT8 => 1,
141
- NativeType::INT16 => 2,
142
- NativeType::UINT16 => 2,
143
- NativeType::INT32 => 4,
144
- NativeType::UINT32 => 4,
145
- NativeType::INT64 => 8,
146
- NativeType::UINT64 => 8,
147
- NativeType::FLOAT32 => 4,
148
- NativeType::FLOAT64 => 8,
149
- NativeType::LONG => FFI::Platform::LONG_SIZE / 8,
150
- NativeType::ULONG => FFI::Platform::LONG_SIZE / 8,
151
- NativeType::POINTER => FFI::Platform::ADDRESS_SIZE / 8,
119
+ # Used in function prototypes to indicate the arguments are variadic
120
+ :varargs => Type::VARARGS,
152
121
  })
153
122
 
154
- def self.size_to_type(size)
155
- if sz = TypeSizes[size]
156
- return sz
123
+ # Returns a [ String, Pointer ] tuple so the C memory for the string can be freed
124
+ class StrPtrConverter
125
+ extend DataConverter
126
+ native_type Type::POINTER
127
+
128
+ def self.from_native(val, ctx)
129
+ [ val.null? ? Qnil : val.get_string(0), val ]
157
130
  end
158
131
 
159
- # Be like C, use int as the default type size.
160
- return :int
161
132
  end
133
+
134
+ typedef(StrPtrConverter, :strptr)
135
+
162
136
  def self.type_size(type)
163
- if sz = SizeTypes[find_type(type)]
164
- return sz
165
- end
166
- raise ArgumentError, "Unknown native type"
137
+ find_type(type).size
167
138
  end
168
139
 
169
140
  # Load all the platform dependent types
170
141
  begin
171
- File.open(File.join(FFI::Platform::CONF_DIR, 'types.conf'), "r") do |f|
142
+ File.open(File.join(Platform::CONF_DIR, 'types.conf'), "r") do |f|
172
143
  prefix = "rbx.platform.typedef."
173
144
  f.each_line { |line|
174
145
  if line.index(prefix) == 0
175
146
  new_type, orig_type = line.chomp.slice(prefix.length..-1).split(/\s*=\s*/)
176
- add_typedef(orig_type.to_sym, new_type.to_sym)
147
+ typedef(orig_type.to_sym, new_type.to_sym)
177
148
  end
178
149
  }
179
150
  end
@@ -1,3 +1,23 @@
1
+ #
2
+ # Copyright (C) 2008-2010 Wayne Meissner
3
+ #
4
+ # All rights reserved.
5
+ #
6
+ # This file is part of ruby-ffi.
7
+ #
8
+ # This code is free software: you can redistribute it and/or modify it under
9
+ # the terms of the GNU Lesser General Public License version 3 only, as
10
+ # published by the Free Software Foundation.
11
+ #
12
+ # This code is distributed in the hope that it will be useful, but WITHOUT
13
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
15
+ # version 3 for more details.
16
+ #
17
+ # You should have received a copy of the GNU Lesser General Public License
18
+ # version 3 along with this work. If not, see <http://www.gnu.org/licenses/>.
19
+ #
20
+
1
21
  require 'ffi/struct'
2
22
 
3
23
  module FFI
@@ -1,31 +1,21 @@
1
1
  #
2
2
  # Copyright (C) 2008, 2009 Wayne Meissner
3
3
  # Copyright (C) 2009 Luc Heinrich
4
- #
5
4
  # All rights reserved.
6
5
  #
7
- # Redistribution and use in source and binary forms, with or without
8
- # modification, are permitted provided that the following conditions are met:
6
+ # This file is part of ruby-ffi.
9
7
  #
10
- # * Redistributions of source code must retain the above copyright notice, this
11
- # list of conditions and the following disclaimer.
12
- # * Redistributions in binary form must reproduce the above copyright notice
13
- # this list of conditions and the following disclaimer in the documentation
14
- # and/or other materials provided with the distribution.
15
- # * Neither the name of the Evan Phoenix nor the names of its contributors
16
- # may be used to endorse or promote products derived from this software
17
- # without specific prior written permission.
8
+ # This code is free software: you can redistribute it and/or modify it under
9
+ # the terms of the GNU Lesser General Public License version 3 only, as
10
+ # published by the Free Software Foundation.
18
11
  #
19
- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
- # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
- # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
- # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
23
- # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
- # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
- # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
- # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
- # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
- # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
12
+ # This code is distributed in the hope that it will be useful, but WITHOUT
13
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
15
+ # version 3 for more details.
16
+ #
17
+ # You should have received a copy of the GNU Lesser General Public License
18
+ # version 3 along with this work. If not, see <http://www.gnu.org/licenses/>.
29
19
 
30
20
  module FFI
31
21
  class VariadicInvoker
@@ -33,9 +23,11 @@ module FFI
33
23
  @fixed = Array.new
34
24
  @type_map = type_map
35
25
  arg_types.each_with_index do |type, i|
36
- @fixed << type unless type == FFI::NativeType::VARARGS
26
+ @fixed << type unless type == Type::VARARGS
37
27
  end
38
28
  end
29
+
30
+
39
31
  def call(*args, &block)
40
32
  param_types = Array.new(@fixed)
41
33
  param_values = Array.new
@@ -50,5 +42,24 @@ module FFI
50
42
  end
51
43
  invoke(param_types, param_values, &block)
52
44
  end
45
+
46
+ #
47
+ # Attach the invoker to module +mod+ as +mname+
48
+ #
49
+ def attach(mod, mname)
50
+ invoker = self
51
+ params = "*args"
52
+ call = "call"
53
+ mod.module_eval <<-code
54
+ @@#{mname} = invoker
55
+ def self.#{mname}(#{params})
56
+ @@#{mname}.#{call}(#{params})
57
+ end
58
+ def #{mname}(#{params})
59
+ @@#{mname}.#{call}(#{params})
60
+ end
61
+ code
62
+ invoker
63
+ end
53
64
  end
54
65
  end
Binary file
@@ -0,0 +1,23 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
2
+
3
+ describe "async callback" do
4
+ module LibTest
5
+ extend FFI::Library
6
+ ffi_lib TestLibrary::PATH
7
+ AsyncIntCallback = callback [ :int ], :void
8
+
9
+ # @blocking = true
10
+ attach_function :testAsyncCallback, [ AsyncIntCallback, :int ], :void, :blocking => true
11
+ end
12
+
13
+ unless RUBY_VERSION =~ /1.8/
14
+ it ":int (0x7fffffff) argument" do
15
+ v = 0xdeadbeef
16
+ called = false
17
+ cb = Proc.new {|i| v = i; called = true }
18
+ LibTest.testAsyncCallback(cb, 0x7fffffff)
19
+ called.should be_true
20
+ v.should == 0x7fffffff
21
+ end
22
+ end
23
+ end
@@ -31,6 +31,10 @@ describe "Callback" do
31
31
  module LibTest
32
32
  extend FFI::Library
33
33
  ffi_lib TestLibrary::PATH
34
+ class S8F32S32 < FFI::Struct
35
+ layout :s8, :char, :f32, :float, :s32, :int
36
+ end
37
+
34
38
  callback :cbVrS8, [ ], :char
35
39
  callback :cbVrU8, [ ], :uchar
36
40
  callback :cbVrS16, [ ], :short
@@ -49,6 +53,10 @@ describe "Callback" do
49
53
  callback :cbLrV, [ :long ], :void
50
54
  callback :cbULrV, [ :ulong ], :void
51
55
  callback :cbLrV, [ :long_long ], :void
56
+ callback :cbVrT, [ ], S8F32S32.by_value
57
+ callback :cbTrV, [ S8F32S32.by_value ], :void
58
+ callback :cbYrV, [ S8F32S32.ptr ], :void
59
+ callback :cbVrY, [ ], S8F32S32.ptr
52
60
 
53
61
  attach_function :testCallbackVrS8, :testClosureVrB, [ :cbVrS8 ], :char
54
62
  attach_function :testCallbackVrU8, :testClosureVrB, [ :cbVrU8 ], :uchar
@@ -62,7 +70,10 @@ describe "Callback" do
62
70
  attach_function :testCallbackVrS64, :testClosureVrLL, [ :cbVrS64 ], :long_long
63
71
  attach_function :testCallbackVrU64, :testClosureVrLL, [ :cbVrU64 ], :ulong_long
64
72
  attach_function :testCallbackVrP, :testClosureVrP, [ :cbVrP ], :pointer
73
+ attach_function :testCallbackVrY, :testClosureVrP, [ :cbVrY ], S8F32S32.ptr
65
74
  attach_function :testCallbackCrV, :testClosureBrV, [ :cbCrV, :char ], :void
75
+ attach_function :testCallbackVrT, :testClosureVrT, [ :cbVrT ], S8F32S32.by_value
76
+ attach_function :testCallbackTrV, :testClosureTrV, [ :cbTrV, S8F32S32.ptr ], :void
66
77
  attach_variable :cbVrS8, :gvar_pointer, :cbVrS8
67
78
  attach_variable :pVrS8, :gvar_pointer, :pointer
68
79
  attach_function :testGVarCallbackVrS8, :testClosureVrB, [ :pointer ], :char
@@ -217,6 +228,33 @@ describe "Callback" do
217
228
  LibTest.testCallbackVrP { p }.should == p
218
229
  end
219
230
 
231
+
232
+ it "returning struct by value" do
233
+ s = LibTest::S8F32S32.new
234
+ s[:s8] = 0x12
235
+ s[:s32] = 0x1eefbeef
236
+ s[:f32] = 1.234567
237
+ ret = LibTest.testCallbackVrT { s }
238
+ ret[:s8].should == s[:s8]
239
+ ret[:f32].should == s[:f32]
240
+ ret[:s32].should == s[:s32]
241
+
242
+ end
243
+
244
+ it "struct by value parameter" do
245
+ s = LibTest::S8F32S32.new
246
+ s[:s8] = 0x12
247
+ s[:s32] = 0x1eefbeef
248
+ s[:f32] = 1.234567
249
+ s2 = LibTest::S8F32S32.new
250
+ LibTest.testCallbackTrV(s) do |struct|
251
+ s2[:s8] = struct[:s8]
252
+ s2[:f32] = struct[:f32]
253
+ s2[:s32] = struct[:s32]
254
+ end
255
+ end
256
+
257
+
220
258
  it "global variable" do
221
259
  proc = Proc.new { 0x1e }
222
260
  LibTest.cbVrS8 = proc
@@ -344,6 +382,8 @@ describe "Callback" do
344
382
  end
345
383
 
346
384
  end
385
+
386
+
347
387
  describe "Callback with " do
348
388
  #
349
389
  # Test callbacks that take an argument, returning void
@@ -351,6 +391,11 @@ describe "Callback with " do
351
391
  module LibTest
352
392
  extend FFI::Library
353
393
  ffi_lib TestLibrary::PATH
394
+
395
+ class S8F32S32 < FFI::Struct
396
+ layout :s8, :char, :f32, :float, :s32, :int
397
+ end
398
+
354
399
  callback :cbS8rV, [ :char ], :void
355
400
  callback :cbU8rV, [ :uchar ], :void
356
401
  callback :cbS16rV, [ :short ], :void
@@ -364,6 +409,7 @@ describe "Callback with " do
364
409
  callback :cbULrV, [ :ulong ], :void
365
410
  callback :cbArV, [ :string ], :void
366
411
  callback :cbPrV, [ :pointer], :void
412
+ callback :cbYrV, [ S8F32S32.ptr ], :void
367
413
 
368
414
  callback :cbS64rV, [ :long_long ], :void
369
415
  attach_function :testCallbackCrV, :testClosureBrV, [ :cbS8rV, :char ], :void
@@ -380,6 +426,7 @@ describe "Callback with " do
380
426
  attach_function :testCallbackLLrV, :testClosureLLrV, [ :cbS64rV, :long_long ], :void
381
427
  attach_function :testCallbackArV, :testClosurePrV, [ :cbArV, :string ], :void
382
428
  attach_function :testCallbackPrV, :testClosurePrV, [ :cbPrV, :pointer], :void
429
+ attach_function :testCallbackYrV, :testClosurePrV, [ :cbYrV, S8F32S32.in ], :void
383
430
  end
384
431
  it ":char (0) argument" do
385
432
  v = 0xdeadbeef
@@ -588,4 +635,19 @@ describe "Callback with " do
588
635
  LibTest.testCallbackPrV(nil) { |i| v = i }
589
636
  v.should == FFI::Pointer::NULL
590
637
  end
638
+ it "struct by reference argument" do
639
+ v = nil
640
+ magic = LibTest::S8F32S32.new
641
+ LibTest.testCallbackYrV(magic) { |i| v = i }
642
+ v.class.should == magic.class
643
+ v.pointer == magic.pointer
644
+ end
645
+
646
+ it "struct by reference argument with nil value" do
647
+ v = LibTest::S8F32S32.new
648
+ LibTest.testCallbackYrV(nil) { |i| v = i }
649
+ v.is_a?(FFI::Struct).should be_true
650
+ v.pointer.should == FFI::Pointer::NULL
651
+ end
652
+
591
653
  end # unless true