fiddle 1.0.0.beta1
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.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +41 -0
- data/Rakefile +13 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/ext/fiddle/closure.c +345 -0
- data/ext/fiddle/closure.h +8 -0
- data/ext/fiddle/conversions.c +141 -0
- data/ext/fiddle/conversions.h +44 -0
- data/ext/fiddle/extconf.rb +183 -0
- data/ext/fiddle/extlibs +2 -0
- data/ext/fiddle/fiddle.c +454 -0
- data/ext/fiddle/fiddle.h +138 -0
- data/ext/fiddle/function.c +315 -0
- data/ext/fiddle/function.h +8 -0
- data/ext/fiddle/handle.c +479 -0
- data/ext/fiddle/pointer.c +721 -0
- data/ext/fiddle/win32/fficonfig.h +29 -0
- data/ext/fiddle/win32/libffi-3.2.1-mswin.patch +191 -0
- data/ext/fiddle/win32/libffi-config.rb +48 -0
- data/ext/fiddle/win32/libffi.mk.tmpl +96 -0
- data/fiddle.gemspec +23 -0
- data/lib/fiddle.rb +56 -0
- data/lib/fiddle/closure.rb +49 -0
- data/lib/fiddle/cparser.rb +194 -0
- data/lib/fiddle/function.rb +18 -0
- data/lib/fiddle/import.rb +318 -0
- data/lib/fiddle/pack.rb +129 -0
- data/lib/fiddle/struct.rb +244 -0
- data/lib/fiddle/types.rb +72 -0
- data/lib/fiddle/value.rb +113 -0
- metadata +136 -0
data/lib/fiddle/pack.rb
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
# frozen_string_literal: false
|
2
|
+
require 'fiddle'
|
3
|
+
|
4
|
+
module Fiddle
|
5
|
+
module PackInfo # :nodoc: all
|
6
|
+
ALIGN_MAP = {
|
7
|
+
TYPE_VOIDP => ALIGN_VOIDP,
|
8
|
+
TYPE_CHAR => ALIGN_CHAR,
|
9
|
+
TYPE_SHORT => ALIGN_SHORT,
|
10
|
+
TYPE_INT => ALIGN_INT,
|
11
|
+
TYPE_LONG => ALIGN_LONG,
|
12
|
+
TYPE_FLOAT => ALIGN_FLOAT,
|
13
|
+
TYPE_DOUBLE => ALIGN_DOUBLE,
|
14
|
+
-TYPE_CHAR => ALIGN_CHAR,
|
15
|
+
-TYPE_SHORT => ALIGN_SHORT,
|
16
|
+
-TYPE_INT => ALIGN_INT,
|
17
|
+
-TYPE_LONG => ALIGN_LONG,
|
18
|
+
}
|
19
|
+
|
20
|
+
PACK_MAP = {
|
21
|
+
TYPE_VOIDP => ((SIZEOF_VOIDP == SIZEOF_LONG_LONG) ? "q" : "l!"),
|
22
|
+
TYPE_CHAR => "c",
|
23
|
+
TYPE_SHORT => "s!",
|
24
|
+
TYPE_INT => "i!",
|
25
|
+
TYPE_LONG => "l!",
|
26
|
+
TYPE_FLOAT => "f",
|
27
|
+
TYPE_DOUBLE => "d",
|
28
|
+
-TYPE_CHAR => "c",
|
29
|
+
-TYPE_SHORT => "s!",
|
30
|
+
-TYPE_INT => "i!",
|
31
|
+
-TYPE_LONG => "l!",
|
32
|
+
}
|
33
|
+
|
34
|
+
SIZE_MAP = {
|
35
|
+
TYPE_VOIDP => SIZEOF_VOIDP,
|
36
|
+
TYPE_CHAR => SIZEOF_CHAR,
|
37
|
+
TYPE_SHORT => SIZEOF_SHORT,
|
38
|
+
TYPE_INT => SIZEOF_INT,
|
39
|
+
TYPE_LONG => SIZEOF_LONG,
|
40
|
+
TYPE_FLOAT => SIZEOF_FLOAT,
|
41
|
+
TYPE_DOUBLE => SIZEOF_DOUBLE,
|
42
|
+
-TYPE_CHAR => SIZEOF_CHAR,
|
43
|
+
-TYPE_SHORT => SIZEOF_SHORT,
|
44
|
+
-TYPE_INT => SIZEOF_INT,
|
45
|
+
-TYPE_LONG => SIZEOF_LONG,
|
46
|
+
}
|
47
|
+
if defined?(TYPE_LONG_LONG)
|
48
|
+
ALIGN_MAP[TYPE_LONG_LONG] = ALIGN_MAP[-TYPE_LONG_LONG] = ALIGN_LONG_LONG
|
49
|
+
PACK_MAP[TYPE_LONG_LONG] = PACK_MAP[-TYPE_LONG_LONG] = "q"
|
50
|
+
SIZE_MAP[TYPE_LONG_LONG] = SIZE_MAP[-TYPE_LONG_LONG] = SIZEOF_LONG_LONG
|
51
|
+
end
|
52
|
+
|
53
|
+
def align(addr, align)
|
54
|
+
d = addr % align
|
55
|
+
if( d == 0 )
|
56
|
+
addr
|
57
|
+
else
|
58
|
+
addr + (align - d)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
module_function :align
|
62
|
+
end
|
63
|
+
|
64
|
+
class Packer # :nodoc: all
|
65
|
+
include PackInfo
|
66
|
+
|
67
|
+
def self.[](*types)
|
68
|
+
new(types)
|
69
|
+
end
|
70
|
+
|
71
|
+
def initialize(types)
|
72
|
+
parse_types(types)
|
73
|
+
end
|
74
|
+
|
75
|
+
def size()
|
76
|
+
@size
|
77
|
+
end
|
78
|
+
|
79
|
+
def pack(ary)
|
80
|
+
case SIZEOF_VOIDP
|
81
|
+
when SIZEOF_LONG
|
82
|
+
ary.pack(@template)
|
83
|
+
when SIZEOF_LONG_LONG
|
84
|
+
ary.pack(@template)
|
85
|
+
else
|
86
|
+
raise(RuntimeError, "sizeof(void*)?")
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def unpack(ary)
|
91
|
+
case SIZEOF_VOIDP
|
92
|
+
when SIZEOF_LONG
|
93
|
+
ary.join().unpack(@template)
|
94
|
+
when SIZEOF_LONG_LONG
|
95
|
+
ary.join().unpack(@template)
|
96
|
+
else
|
97
|
+
raise(RuntimeError, "sizeof(void*)?")
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
private
|
102
|
+
|
103
|
+
def parse_types(types)
|
104
|
+
@template = ""
|
105
|
+
addr = 0
|
106
|
+
types.each{|t|
|
107
|
+
orig_addr = addr
|
108
|
+
if( t.is_a?(Array) )
|
109
|
+
addr = align(orig_addr, ALIGN_MAP[TYPE_VOIDP])
|
110
|
+
else
|
111
|
+
addr = align(orig_addr, ALIGN_MAP[t])
|
112
|
+
end
|
113
|
+
d = addr - orig_addr
|
114
|
+
if( d > 0 )
|
115
|
+
@template << "x#{d}"
|
116
|
+
end
|
117
|
+
if( t.is_a?(Array) )
|
118
|
+
@template << (PACK_MAP[t[0]] * t[1])
|
119
|
+
addr += (SIZE_MAP[t[0]] * t[1])
|
120
|
+
else
|
121
|
+
@template << PACK_MAP[t]
|
122
|
+
addr += SIZE_MAP[t]
|
123
|
+
end
|
124
|
+
}
|
125
|
+
addr = align(addr, ALIGN_MAP[TYPE_VOIDP])
|
126
|
+
@size = addr
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,244 @@
|
|
1
|
+
# frozen_string_literal: false
|
2
|
+
require 'fiddle'
|
3
|
+
require 'fiddle/value'
|
4
|
+
require 'fiddle/pack'
|
5
|
+
|
6
|
+
module Fiddle
|
7
|
+
# C struct shell
|
8
|
+
class CStruct
|
9
|
+
# accessor to Fiddle::CStructEntity
|
10
|
+
def CStruct.entity_class
|
11
|
+
CStructEntity
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# C union shell
|
16
|
+
class CUnion
|
17
|
+
# accessor to Fiddle::CUnionEntity
|
18
|
+
def CUnion.entity_class
|
19
|
+
CUnionEntity
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Used to construct C classes (CUnion, CStruct, etc)
|
24
|
+
#
|
25
|
+
# Fiddle::Importer#struct and Fiddle::Importer#union wrap this functionality in an
|
26
|
+
# easy-to-use manner.
|
27
|
+
module CStructBuilder
|
28
|
+
# Construct a new class given a C:
|
29
|
+
# * class +klass+ (CUnion, CStruct, or other that provide an
|
30
|
+
# #entity_class)
|
31
|
+
# * +types+ (Fiddle::TYPE_INT, Fiddle::TYPE_SIZE_T, etc., see the C types
|
32
|
+
# constants)
|
33
|
+
# * corresponding +members+
|
34
|
+
#
|
35
|
+
# Fiddle::Importer#struct and Fiddle::Importer#union wrap this functionality in an
|
36
|
+
# easy-to-use manner.
|
37
|
+
#
|
38
|
+
# Example:
|
39
|
+
#
|
40
|
+
# require 'fiddle/struct'
|
41
|
+
# require 'fiddle/cparser'
|
42
|
+
#
|
43
|
+
# include Fiddle::CParser
|
44
|
+
#
|
45
|
+
# types, members = parse_struct_signature(['int i','char c'])
|
46
|
+
#
|
47
|
+
# MyStruct = Fiddle::CStructBuilder.create(Fiddle::CUnion, types, members)
|
48
|
+
#
|
49
|
+
# obj = MyStruct.allocate
|
50
|
+
#
|
51
|
+
def create(klass, types, members)
|
52
|
+
new_class = Class.new(klass){
|
53
|
+
define_method(:initialize){|addr|
|
54
|
+
@entity = klass.entity_class.new(addr, types)
|
55
|
+
@entity.assign_names(members)
|
56
|
+
}
|
57
|
+
define_method(:to_ptr){ @entity }
|
58
|
+
define_method(:to_i){ @entity.to_i }
|
59
|
+
members.each{|name|
|
60
|
+
define_method(name){ @entity[name] }
|
61
|
+
define_method(name + "="){|val| @entity[name] = val }
|
62
|
+
}
|
63
|
+
}
|
64
|
+
size = klass.entity_class.size(types)
|
65
|
+
new_class.module_eval(<<-EOS, __FILE__, __LINE__+1)
|
66
|
+
def new_class.size()
|
67
|
+
#{size}
|
68
|
+
end
|
69
|
+
def new_class.malloc()
|
70
|
+
addr = Fiddle.malloc(#{size})
|
71
|
+
new(addr)
|
72
|
+
end
|
73
|
+
EOS
|
74
|
+
return new_class
|
75
|
+
end
|
76
|
+
module_function :create
|
77
|
+
end
|
78
|
+
|
79
|
+
# A C struct wrapper
|
80
|
+
class CStructEntity < Fiddle::Pointer
|
81
|
+
include PackInfo
|
82
|
+
include ValueUtil
|
83
|
+
|
84
|
+
# Allocates a C struct with the +types+ provided.
|
85
|
+
#
|
86
|
+
# When the instance is garbage collected, the C function +func+ is called.
|
87
|
+
def CStructEntity.malloc(types, func = nil)
|
88
|
+
addr = Fiddle.malloc(CStructEntity.size(types))
|
89
|
+
CStructEntity.new(addr, types, func)
|
90
|
+
end
|
91
|
+
|
92
|
+
# Returns the offset for the packed sizes for the given +types+.
|
93
|
+
#
|
94
|
+
# Fiddle::CStructEntity.size(
|
95
|
+
# [ Fiddle::TYPE_DOUBLE,
|
96
|
+
# Fiddle::TYPE_INT,
|
97
|
+
# Fiddle::TYPE_CHAR,
|
98
|
+
# Fiddle::TYPE_VOIDP ]) #=> 24
|
99
|
+
def CStructEntity.size(types)
|
100
|
+
offset = 0
|
101
|
+
|
102
|
+
max_align = types.map { |type, count = 1|
|
103
|
+
last_offset = offset
|
104
|
+
|
105
|
+
align = PackInfo::ALIGN_MAP[type]
|
106
|
+
offset = PackInfo.align(last_offset, align) +
|
107
|
+
(PackInfo::SIZE_MAP[type] * count)
|
108
|
+
|
109
|
+
align
|
110
|
+
}.max
|
111
|
+
|
112
|
+
PackInfo.align(offset, max_align)
|
113
|
+
end
|
114
|
+
|
115
|
+
# Wraps the C pointer +addr+ as a C struct with the given +types+.
|
116
|
+
#
|
117
|
+
# When the instance is garbage collected, the C function +func+ is called.
|
118
|
+
#
|
119
|
+
# See also Fiddle::Pointer.new
|
120
|
+
def initialize(addr, types, func = nil)
|
121
|
+
set_ctypes(types)
|
122
|
+
super(addr, @size, func)
|
123
|
+
end
|
124
|
+
|
125
|
+
# Set the names of the +members+ in this C struct
|
126
|
+
def assign_names(members)
|
127
|
+
@members = members
|
128
|
+
end
|
129
|
+
|
130
|
+
# Calculates the offsets and sizes for the given +types+ in the struct.
|
131
|
+
def set_ctypes(types)
|
132
|
+
@ctypes = types
|
133
|
+
@offset = []
|
134
|
+
offset = 0
|
135
|
+
|
136
|
+
max_align = types.map { |type, count = 1|
|
137
|
+
orig_offset = offset
|
138
|
+
align = ALIGN_MAP[type]
|
139
|
+
offset = PackInfo.align(orig_offset, align)
|
140
|
+
|
141
|
+
@offset << offset
|
142
|
+
|
143
|
+
offset += (SIZE_MAP[type] * count)
|
144
|
+
|
145
|
+
align
|
146
|
+
}.max
|
147
|
+
|
148
|
+
@size = PackInfo.align(offset, max_align)
|
149
|
+
end
|
150
|
+
|
151
|
+
# Fetch struct member +name+
|
152
|
+
def [](name)
|
153
|
+
idx = @members.index(name)
|
154
|
+
if( idx.nil? )
|
155
|
+
raise(ArgumentError, "no such member: #{name}")
|
156
|
+
end
|
157
|
+
ty = @ctypes[idx]
|
158
|
+
if( ty.is_a?(Array) )
|
159
|
+
r = super(@offset[idx], SIZE_MAP[ty[0]] * ty[1])
|
160
|
+
else
|
161
|
+
r = super(@offset[idx], SIZE_MAP[ty.abs])
|
162
|
+
end
|
163
|
+
packer = Packer.new([ty])
|
164
|
+
val = packer.unpack([r])
|
165
|
+
case ty
|
166
|
+
when Array
|
167
|
+
case ty[0]
|
168
|
+
when TYPE_VOIDP
|
169
|
+
val = val.collect{|v| Pointer.new(v)}
|
170
|
+
end
|
171
|
+
when TYPE_VOIDP
|
172
|
+
val = Pointer.new(val[0])
|
173
|
+
else
|
174
|
+
val = val[0]
|
175
|
+
end
|
176
|
+
if( ty.is_a?(Integer) && (ty < 0) )
|
177
|
+
return unsigned_value(val, ty)
|
178
|
+
elsif( ty.is_a?(Array) && (ty[0] < 0) )
|
179
|
+
return val.collect{|v| unsigned_value(v,ty[0])}
|
180
|
+
else
|
181
|
+
return val
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
# Set struct member +name+, to value +val+
|
186
|
+
def []=(name, val)
|
187
|
+
idx = @members.index(name)
|
188
|
+
if( idx.nil? )
|
189
|
+
raise(ArgumentError, "no such member: #{name}")
|
190
|
+
end
|
191
|
+
ty = @ctypes[idx]
|
192
|
+
packer = Packer.new([ty])
|
193
|
+
val = wrap_arg(val, ty, [])
|
194
|
+
buff = packer.pack([val].flatten())
|
195
|
+
super(@offset[idx], buff.size, buff)
|
196
|
+
if( ty.is_a?(Integer) && (ty < 0) )
|
197
|
+
return unsigned_value(val, ty)
|
198
|
+
elsif( ty.is_a?(Array) && (ty[0] < 0) )
|
199
|
+
return val.collect{|v| unsigned_value(v,ty[0])}
|
200
|
+
else
|
201
|
+
return val
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
def to_s() # :nodoc:
|
206
|
+
super(@size)
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
# A C union wrapper
|
211
|
+
class CUnionEntity < CStructEntity
|
212
|
+
include PackInfo
|
213
|
+
|
214
|
+
# Allocates a C union the +types+ provided.
|
215
|
+
#
|
216
|
+
# When the instance is garbage collected, the C function +func+ is called.
|
217
|
+
def CUnionEntity.malloc(types, func=nil)
|
218
|
+
addr = Fiddle.malloc(CUnionEntity.size(types))
|
219
|
+
CUnionEntity.new(addr, types, func)
|
220
|
+
end
|
221
|
+
|
222
|
+
# Returns the size needed for the union with the given +types+.
|
223
|
+
#
|
224
|
+
# Fiddle::CUnionEntity.size(
|
225
|
+
# [ Fiddle::TYPE_DOUBLE,
|
226
|
+
# Fiddle::TYPE_INT,
|
227
|
+
# Fiddle::TYPE_CHAR,
|
228
|
+
# Fiddle::TYPE_VOIDP ]) #=> 8
|
229
|
+
def CUnionEntity.size(types)
|
230
|
+
types.map { |type, count = 1|
|
231
|
+
PackInfo::SIZE_MAP[type] * count
|
232
|
+
}.max
|
233
|
+
end
|
234
|
+
|
235
|
+
# Calculate the necessary offset and for each union member with the given
|
236
|
+
# +types+
|
237
|
+
def set_ctypes(types)
|
238
|
+
@ctypes = types
|
239
|
+
@offset = Array.new(types.length, 0)
|
240
|
+
@size = self.class.size types
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
data/lib/fiddle/types.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: false
|
2
|
+
module Fiddle
|
3
|
+
# Adds Windows type aliases to the including class for use with
|
4
|
+
# Fiddle::Importer.
|
5
|
+
#
|
6
|
+
# The aliases added are:
|
7
|
+
# * ATOM
|
8
|
+
# * BOOL
|
9
|
+
# * BYTE
|
10
|
+
# * DWORD
|
11
|
+
# * DWORD32
|
12
|
+
# * DWORD64
|
13
|
+
# * HANDLE
|
14
|
+
# * HDC
|
15
|
+
# * HINSTANCE
|
16
|
+
# * HWND
|
17
|
+
# * LPCSTR
|
18
|
+
# * LPSTR
|
19
|
+
# * PBYTE
|
20
|
+
# * PDWORD
|
21
|
+
# * PHANDLE
|
22
|
+
# * PVOID
|
23
|
+
# * PWORD
|
24
|
+
# * UCHAR
|
25
|
+
# * UINT
|
26
|
+
# * ULONG
|
27
|
+
# * WORD
|
28
|
+
module Win32Types
|
29
|
+
def included(m) # :nodoc:
|
30
|
+
m.module_eval{
|
31
|
+
typealias "DWORD", "unsigned long"
|
32
|
+
typealias "PDWORD", "unsigned long *"
|
33
|
+
typealias "DWORD32", "unsigned long"
|
34
|
+
typealias "DWORD64", "unsigned long long"
|
35
|
+
typealias "WORD", "unsigned short"
|
36
|
+
typealias "PWORD", "unsigned short *"
|
37
|
+
typealias "BOOL", "int"
|
38
|
+
typealias "ATOM", "int"
|
39
|
+
typealias "BYTE", "unsigned char"
|
40
|
+
typealias "PBYTE", "unsigned char *"
|
41
|
+
typealias "UINT", "unsigned int"
|
42
|
+
typealias "ULONG", "unsigned long"
|
43
|
+
typealias "UCHAR", "unsigned char"
|
44
|
+
typealias "HANDLE", "uintptr_t"
|
45
|
+
typealias "PHANDLE", "void*"
|
46
|
+
typealias "PVOID", "void*"
|
47
|
+
typealias "LPCSTR", "char*"
|
48
|
+
typealias "LPSTR", "char*"
|
49
|
+
typealias "HINSTANCE", "unsigned int"
|
50
|
+
typealias "HDC", "unsigned int"
|
51
|
+
typealias "HWND", "unsigned int"
|
52
|
+
}
|
53
|
+
end
|
54
|
+
module_function :included
|
55
|
+
end
|
56
|
+
|
57
|
+
# Adds basic type aliases to the including class for use with Fiddle::Importer.
|
58
|
+
#
|
59
|
+
# The aliases added are +uint+ and +u_int+ (<tt>unsigned int</tt>) and
|
60
|
+
# +ulong+ and +u_long+ (<tt>unsigned long</tt>)
|
61
|
+
module BasicTypes
|
62
|
+
def included(m) # :nodoc:
|
63
|
+
m.module_eval{
|
64
|
+
typealias "uint", "unsigned int"
|
65
|
+
typealias "u_int", "unsigned int"
|
66
|
+
typealias "ulong", "unsigned long"
|
67
|
+
typealias "u_long", "unsigned long"
|
68
|
+
}
|
69
|
+
end
|
70
|
+
module_function :included
|
71
|
+
end
|
72
|
+
end
|
data/lib/fiddle/value.rb
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
# frozen_string_literal: false
|
2
|
+
require 'fiddle'
|
3
|
+
|
4
|
+
module Fiddle
|
5
|
+
module ValueUtil #:nodoc: all
|
6
|
+
def unsigned_value(val, ty)
|
7
|
+
case ty.abs
|
8
|
+
when TYPE_CHAR
|
9
|
+
[val].pack("c").unpack("C")[0]
|
10
|
+
when TYPE_SHORT
|
11
|
+
[val].pack("s!").unpack("S!")[0]
|
12
|
+
when TYPE_INT
|
13
|
+
[val].pack("i!").unpack("I!")[0]
|
14
|
+
when TYPE_LONG
|
15
|
+
[val].pack("l!").unpack("L!")[0]
|
16
|
+
when TYPE_LONG_LONG
|
17
|
+
[val].pack("q").unpack("Q")[0]
|
18
|
+
else
|
19
|
+
val
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def signed_value(val, ty)
|
24
|
+
case ty.abs
|
25
|
+
when TYPE_CHAR
|
26
|
+
[val].pack("C").unpack("c")[0]
|
27
|
+
when TYPE_SHORT
|
28
|
+
[val].pack("S!").unpack("s!")[0]
|
29
|
+
when TYPE_INT
|
30
|
+
[val].pack("I!").unpack("i!")[0]
|
31
|
+
when TYPE_LONG
|
32
|
+
[val].pack("L!").unpack("l!")[0]
|
33
|
+
when TYPE_LONG_LONG
|
34
|
+
[val].pack("Q").unpack("q")[0]
|
35
|
+
else
|
36
|
+
val
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def wrap_args(args, tys, funcs, &block)
|
41
|
+
result = []
|
42
|
+
tys ||= []
|
43
|
+
args.each_with_index{|arg, idx|
|
44
|
+
result.push(wrap_arg(arg, tys[idx], funcs, &block))
|
45
|
+
}
|
46
|
+
result
|
47
|
+
end
|
48
|
+
|
49
|
+
def wrap_arg(arg, ty, funcs = [], &block)
|
50
|
+
funcs ||= []
|
51
|
+
case arg
|
52
|
+
when nil
|
53
|
+
return 0
|
54
|
+
when Pointer
|
55
|
+
return arg.to_i
|
56
|
+
when IO
|
57
|
+
case ty
|
58
|
+
when TYPE_VOIDP
|
59
|
+
return Pointer[arg].to_i
|
60
|
+
else
|
61
|
+
return arg.to_i
|
62
|
+
end
|
63
|
+
when Function
|
64
|
+
if( block )
|
65
|
+
arg.bind_at_call(&block)
|
66
|
+
funcs.push(arg)
|
67
|
+
elsif !arg.bound?
|
68
|
+
raise(RuntimeError, "block must be given.")
|
69
|
+
end
|
70
|
+
return arg.to_i
|
71
|
+
when String
|
72
|
+
if( ty.is_a?(Array) )
|
73
|
+
return arg.unpack('C*')
|
74
|
+
else
|
75
|
+
case SIZEOF_VOIDP
|
76
|
+
when SIZEOF_LONG
|
77
|
+
return [arg].pack("p").unpack("l!")[0]
|
78
|
+
when SIZEOF_LONG_LONG
|
79
|
+
return [arg].pack("p").unpack("q")[0]
|
80
|
+
else
|
81
|
+
raise(RuntimeError, "sizeof(void*)?")
|
82
|
+
end
|
83
|
+
end
|
84
|
+
when Float, Integer
|
85
|
+
return arg
|
86
|
+
when Array
|
87
|
+
if( ty.is_a?(Array) ) # used only by struct
|
88
|
+
case ty[0]
|
89
|
+
when TYPE_VOIDP
|
90
|
+
return arg.collect{|v| Integer(v)}
|
91
|
+
when TYPE_CHAR
|
92
|
+
if( arg.is_a?(String) )
|
93
|
+
return val.unpack('C*')
|
94
|
+
end
|
95
|
+
end
|
96
|
+
return arg
|
97
|
+
else
|
98
|
+
return arg
|
99
|
+
end
|
100
|
+
else
|
101
|
+
if( arg.respond_to?(:to_ptr) )
|
102
|
+
return arg.to_ptr.to_i
|
103
|
+
else
|
104
|
+
begin
|
105
|
+
return Integer(arg)
|
106
|
+
rescue
|
107
|
+
raise(ArgumentError, "unknown argument type: #{arg.class}")
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|