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.
- data/History.txt +7 -0
- data/LICENSE +10 -21
- data/README.rdoc +1 -0
- data/Rakefile +4 -2
- data/ext/ffi_c/AbstractMemory.c +103 -38
- data/ext/ffi_c/AbstractMemory.h +15 -22
- data/ext/ffi_c/Buffer.c +61 -22
- data/ext/ffi_c/Call.c +52 -540
- data/ext/ffi_c/Call.h +1 -1
- data/ext/ffi_c/DataConverter.c +62 -0
- data/ext/ffi_c/DynamicLibrary.c +21 -1
- data/ext/ffi_c/Function.c +315 -30
- data/ext/ffi_c/MappedType.c +146 -0
- data/ext/ffi_c/MappedType.h +57 -0
- data/ext/ffi_c/MemoryPointer.c +12 -33
- data/ext/ffi_c/Platform.c +2 -0
- data/ext/ffi_c/Pointer.c +66 -28
- data/ext/ffi_c/Struct.c +19 -306
- data/ext/ffi_c/Struct.h +6 -0
- data/ext/ffi_c/StructByReference.c +150 -0
- data/ext/ffi_c/StructByReference.h +50 -0
- data/ext/ffi_c/StructLayout.c +25 -14
- data/ext/ffi_c/Type.c +39 -68
- data/ext/ffi_c/Type.h +12 -22
- data/ext/ffi_c/Types.c +20 -5
- data/ext/ffi_c/Types.h +7 -7
- data/ext/ffi_c/Variadic.c +21 -17
- data/ext/ffi_c/extconf.rb +4 -0
- data/ext/ffi_c/ffi.c +8 -2
- data/ext/ffi_c/rbffi.h +1 -0
- data/lib/ffi/autopointer.rb +23 -22
- data/lib/ffi/enum.rb +36 -21
- data/lib/ffi/errno.rb +20 -0
- data/lib/ffi/ffi.rb +13 -80
- data/lib/ffi/io.rb +12 -20
- data/lib/ffi/library.rb +109 -92
- data/lib/ffi/managedstruct.rb +1 -1
- data/lib/ffi/memorypointer.rb +15 -21
- data/lib/ffi/platform.rb +24 -28
- data/lib/ffi/pointer.rb +14 -21
- data/lib/ffi/struct.rb +98 -49
- data/lib/ffi/struct_layout_builder.rb +158 -0
- data/lib/ffi/types.rb +99 -128
- data/lib/ffi/union.rb +20 -0
- data/lib/ffi/variadic.rb +33 -22
- data/lib/ffi_c.so +0 -0
- data/spec/ffi/async_callback_spec.rb +23 -0
- data/spec/ffi/callback_spec.rb +62 -0
- data/spec/ffi/custom_param_type.rb +31 -0
- data/spec/ffi/custom_type_spec.rb +73 -0
- data/spec/ffi/enum_spec.rb +19 -0
- data/spec/ffi/ffi_spec.rb +24 -0
- data/spec/ffi/pointer_spec.rb +15 -0
- data/spec/ffi/rbx/memory_pointer_spec.rb +7 -1
- data/spec/ffi/strptr_spec.rb +36 -0
- data/spec/ffi/struct_packed_spec.rb +46 -0
- data/spec/ffi/struct_spec.rb +19 -5
- data/spec/ffi/typedef_spec.rb +14 -0
- data/tasks/setup.rb +2 -1
- metadata +15 -6
- data/ext/ffi_c/AutoPointer.c +0 -60
- data/ext/ffi_c/AutoPointer.h +0 -18
- data/lib/1.8/ffi_c.so +0 -0
- data/lib/1.9/ffi_c.so +0 -0
data/lib/ffi/types.rb
CHANGED
@@ -1,179 +1,150 @@
|
|
1
1
|
#
|
2
|
-
# Copyright (C) 2008
|
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
|
-
#
|
8
|
-
# modification, are permitted provided that the following conditions are met:
|
5
|
+
# This file is part of ruby-ffi.
|
9
6
|
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
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
|
-
|
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
|
-
|
54
|
-
|
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
|
-
|
63
|
-
|
31
|
+
def self.find_type(name, type_map = nil)
|
32
|
+
if name.is_a?(Type)
|
33
|
+
name
|
64
34
|
|
65
|
-
|
66
|
-
|
35
|
+
elsif type_map && type_map.has_key?(name)
|
36
|
+
type_map[name]
|
67
37
|
|
68
|
-
|
69
|
-
|
38
|
+
elsif TypeDefs.has_key?(name)
|
39
|
+
TypeDefs[name]
|
70
40
|
|
71
|
-
|
72
|
-
|
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
|
-
|
75
|
-
|
49
|
+
TypeDefs.merge!({
|
50
|
+
# The C void type; only useful for function return types
|
51
|
+
:void => Type::VOID,
|
76
52
|
|
77
|
-
|
78
|
-
|
53
|
+
# C boolean type
|
54
|
+
:bool => Type::BOOL,
|
79
55
|
|
80
|
-
|
81
|
-
|
56
|
+
# C nul-terminated string
|
57
|
+
:string => Type::STRING,
|
82
58
|
|
83
|
-
|
84
|
-
|
59
|
+
# C signed char
|
60
|
+
:char => Type::CHAR,
|
61
|
+
# C unsigned char
|
62
|
+
:uchar => Type::UCHAR,
|
85
63
|
|
86
|
-
|
87
|
-
|
64
|
+
# C signed short
|
65
|
+
:short => Type::SHORT,
|
66
|
+
# C unsigned short
|
67
|
+
:ushort => Type::USHORT,
|
88
68
|
|
89
|
-
|
90
|
-
|
69
|
+
# C signed int
|
70
|
+
:int => Type::INT,
|
71
|
+
# C unsigned int
|
72
|
+
:uint => Type::UINT,
|
91
73
|
|
92
|
-
|
93
|
-
|
74
|
+
# C signed long
|
75
|
+
:long => Type::LONG,
|
94
76
|
|
95
|
-
|
96
|
-
|
77
|
+
# C unsigned long
|
78
|
+
:ulong => Type::ULONG,
|
97
79
|
|
98
|
-
|
99
|
-
|
80
|
+
# C signed long long integer
|
81
|
+
:long_long => Type::LONG_LONG,
|
100
82
|
|
101
|
-
|
102
|
-
|
83
|
+
# C unsigned long long integer
|
84
|
+
:ulong_long => Type::ULONG_LONG,
|
103
85
|
|
104
|
-
|
105
|
-
|
86
|
+
# C single precision float
|
87
|
+
:float => Type::FLOAT,
|
106
88
|
|
107
|
-
|
108
|
-
|
89
|
+
# C double precision float
|
90
|
+
:double => Type::DOUBLE,
|
109
91
|
|
110
|
-
|
111
|
-
|
92
|
+
# Native memory address
|
93
|
+
:pointer => Type::POINTER,
|
112
94
|
|
113
|
-
|
114
|
-
|
95
|
+
# 8 bit signed integer
|
96
|
+
:int8 => Type::INT8,
|
97
|
+
# 8 bit unsigned integer
|
98
|
+
:uint8 => Type::UINT8,
|
115
99
|
|
116
|
-
|
117
|
-
|
100
|
+
# 16 bit signed integer
|
101
|
+
:int16 => Type::INT16,
|
102
|
+
# 16 bit unsigned integer
|
103
|
+
:uint16 => Type::UINT16,
|
118
104
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
105
|
+
# 32 bit signed integer
|
106
|
+
:int32 => Type::INT32,
|
107
|
+
# 32 bit unsigned integer
|
108
|
+
:uint32 => Type::UINT32,
|
123
109
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
110
|
+
# 64 bit signed integer
|
111
|
+
:int64 => Type::INT64,
|
112
|
+
# 64 bit unsigned integer
|
113
|
+
:uint64 => Type::UINT64,
|
128
114
|
|
129
|
-
|
130
|
-
|
115
|
+
:buffer_in => Type::BUFFER_IN,
|
116
|
+
:buffer_out => Type::BUFFER_OUT,
|
117
|
+
:buffer_inout => Type::BUFFER_INOUT,
|
131
118
|
|
132
|
-
|
133
|
-
|
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
|
-
|
155
|
-
|
156
|
-
|
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
|
-
|
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(
|
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
|
-
|
147
|
+
typedef(orig_type.to_sym, new_type.to_sym)
|
177
148
|
end
|
178
149
|
}
|
179
150
|
end
|
data/lib/ffi/union.rb
CHANGED
@@ -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
|
data/lib/ffi/variadic.rb
CHANGED
@@ -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
|
-
#
|
8
|
-
# modification, are permitted provided that the following conditions are met:
|
6
|
+
# This file is part of ruby-ffi.
|
9
7
|
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
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
|
-
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
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 ==
|
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
|
data/lib/ffi_c.so
ADDED
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
|
data/spec/ffi/callback_spec.rb
CHANGED
@@ -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
|