fiddle 1.0.0 → 1.0.5
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 +4 -4
- data/README.md +52 -1
- data/Rakefile +4 -5
- data/bin/downloader.rb +331 -0
- data/bin/extlibs.rb +262 -0
- data/ext/fiddle/closure.c +5 -4
- data/ext/fiddle/conversions.c +205 -16
- data/ext/fiddle/conversions.h +14 -4
- data/ext/fiddle/depend +85 -0
- data/ext/fiddle/extconf.rb +62 -29
- data/ext/fiddle/extlibs +10 -2
- data/ext/fiddle/fiddle.c +133 -34
- data/ext/fiddle/fiddle.h +96 -32
- data/ext/fiddle/function.c +261 -93
- data/ext/fiddle/handle.c +10 -12
- data/ext/fiddle/memory_view.c +254 -0
- data/ext/fiddle/pinned.c +123 -0
- data/ext/fiddle/pointer.c +147 -24
- data/ext/fiddle/win32/fficonfig.h +0 -0
- data/ext/fiddle/win32/libffi-config.rb +1 -1
- data/ext/fiddle/win32/libffi.mk.tmpl +0 -0
- data/fiddle.gemspec +48 -5
- data/lib/fiddle.rb +3 -1
- data/lib/fiddle/cparser.rb +90 -25
- data/lib/fiddle/function.rb +5 -0
- data/lib/fiddle/import.rb +11 -9
- data/lib/fiddle/pack.rb +14 -7
- data/lib/fiddle/struct.rb +267 -43
- data/lib/fiddle/value.rb +18 -9
- data/lib/fiddle/version.rb +3 -0
- metadata +15 -12
- data/.gitignore +0 -13
- data/.travis.yml +0 -7
- data/Gemfile +0 -4
- data/bin/console +0 -14
- data/bin/setup +0 -8
data/lib/fiddle/function.rb
CHANGED
data/lib/fiddle/import.rb
CHANGED
@@ -83,11 +83,7 @@ module Fiddle
|
|
83
83
|
when Importer
|
84
84
|
lib.handlers
|
85
85
|
else
|
86
|
-
|
87
|
-
Fiddle.dlopen(lib)
|
88
|
-
rescue DLError
|
89
|
-
raise(DLError, "can't load #{lib}")
|
90
|
-
end
|
86
|
+
Fiddle.dlopen(lib)
|
91
87
|
end
|
92
88
|
}.flatten()
|
93
89
|
@handler = CompositeHandler.new(handles)
|
@@ -115,16 +111,21 @@ module Fiddle
|
|
115
111
|
return SIZEOF_INT
|
116
112
|
when TYPE_LONG
|
117
113
|
return SIZEOF_LONG
|
118
|
-
when TYPE_LONG_LONG
|
119
|
-
return SIZEOF_LONG_LONG
|
120
114
|
when TYPE_FLOAT
|
121
115
|
return SIZEOF_FLOAT
|
122
116
|
when TYPE_DOUBLE
|
123
117
|
return SIZEOF_DOUBLE
|
124
118
|
when TYPE_VOIDP
|
125
119
|
return SIZEOF_VOIDP
|
120
|
+
when TYPE_CONST_STRING
|
121
|
+
return SIZEOF_CONST_STRING
|
126
122
|
else
|
127
|
-
|
123
|
+
if defined?(TYPE_LONG_LONG) and
|
124
|
+
ty == TYPE_LONG_LONG
|
125
|
+
return SIZEOF_LONG_LONG
|
126
|
+
else
|
127
|
+
raise(DLError, "unknown type: #{ty}")
|
128
|
+
end
|
128
129
|
end
|
129
130
|
when Class
|
130
131
|
if( ty.instance_methods().include?(:to_ptr) )
|
@@ -154,7 +155,8 @@ module Fiddle
|
|
154
155
|
# :stopdoc:
|
155
156
|
CALL_TYPE_TO_ABI = Hash.new { |h, k|
|
156
157
|
raise RuntimeError, "unsupported call type: #{k}"
|
157
|
-
}.merge({ :stdcall => (
|
158
|
+
}.merge({ :stdcall => Function.const_defined?(:STDCALL) ? Function::STDCALL :
|
159
|
+
Function::DEFAULT,
|
158
160
|
:cdecl => Function::DEFAULT,
|
159
161
|
nil => Function::DEFAULT
|
160
162
|
}).freeze
|
data/lib/fiddle/pack.rb
CHANGED
@@ -18,7 +18,7 @@ module Fiddle
|
|
18
18
|
}
|
19
19
|
|
20
20
|
PACK_MAP = {
|
21
|
-
TYPE_VOIDP =>
|
21
|
+
TYPE_VOIDP => "l!",
|
22
22
|
TYPE_CHAR => "c",
|
23
23
|
TYPE_SHORT => "s!",
|
24
24
|
TYPE_INT => "i!",
|
@@ -48,6 +48,7 @@ module Fiddle
|
|
48
48
|
ALIGN_MAP[TYPE_LONG_LONG] = ALIGN_MAP[-TYPE_LONG_LONG] = ALIGN_LONG_LONG
|
49
49
|
PACK_MAP[TYPE_LONG_LONG] = PACK_MAP[-TYPE_LONG_LONG] = "q"
|
50
50
|
SIZE_MAP[TYPE_LONG_LONG] = SIZE_MAP[-TYPE_LONG_LONG] = SIZEOF_LONG_LONG
|
51
|
+
PACK_MAP[TYPE_VOIDP] = "q" if SIZEOF_LONG_LONG == SIZEOF_VOIDP
|
51
52
|
end
|
52
53
|
|
53
54
|
def align(addr, align)
|
@@ -80,10 +81,13 @@ module Fiddle
|
|
80
81
|
case SIZEOF_VOIDP
|
81
82
|
when SIZEOF_LONG
|
82
83
|
ary.pack(@template)
|
83
|
-
when SIZEOF_LONG_LONG
|
84
|
-
ary.pack(@template)
|
85
84
|
else
|
86
|
-
|
85
|
+
if defined?(TYPE_LONG_LONG) and
|
86
|
+
SIZEOF_VOIDP == SIZEOF_LONG_LONG
|
87
|
+
ary.pack(@template)
|
88
|
+
else
|
89
|
+
raise(RuntimeError, "sizeof(void*)?")
|
90
|
+
end
|
87
91
|
end
|
88
92
|
end
|
89
93
|
|
@@ -91,10 +95,13 @@ module Fiddle
|
|
91
95
|
case SIZEOF_VOIDP
|
92
96
|
when SIZEOF_LONG
|
93
97
|
ary.join().unpack(@template)
|
94
|
-
when SIZEOF_LONG_LONG
|
95
|
-
ary.join().unpack(@template)
|
96
98
|
else
|
97
|
-
|
99
|
+
if defined?(TYPE_LONG_LONG) and
|
100
|
+
SIZEOF_VOIDP == SIZEOF_LONG_LONG
|
101
|
+
ary.join().unpack(@template)
|
102
|
+
else
|
103
|
+
raise(RuntimeError, "sizeof(void*)?")
|
104
|
+
end
|
98
105
|
end
|
99
106
|
end
|
100
107
|
|
data/lib/fiddle/struct.rb
CHANGED
@@ -4,15 +4,72 @@ require 'fiddle/value'
|
|
4
4
|
require 'fiddle/pack'
|
5
5
|
|
6
6
|
module Fiddle
|
7
|
-
# C
|
7
|
+
# A base class for objects representing a C structure
|
8
8
|
class CStruct
|
9
|
+
include Enumerable
|
10
|
+
|
9
11
|
# accessor to Fiddle::CStructEntity
|
10
12
|
def CStruct.entity_class
|
11
13
|
CStructEntity
|
12
14
|
end
|
15
|
+
|
16
|
+
def each
|
17
|
+
return enum_for(__function__) unless block_given?
|
18
|
+
|
19
|
+
self.class.members.each do |name,|
|
20
|
+
yield(self[name])
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def each_pair
|
25
|
+
return enum_for(__function__) unless block_given?
|
26
|
+
|
27
|
+
self.class.members.each do |name,|
|
28
|
+
yield(name, self[name])
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_h
|
33
|
+
hash = {}
|
34
|
+
each_pair do |name, value|
|
35
|
+
hash[name] = unstruct(value)
|
36
|
+
end
|
37
|
+
hash
|
38
|
+
end
|
39
|
+
|
40
|
+
def replace(another)
|
41
|
+
if another.nil?
|
42
|
+
self.class.members.each do |name,|
|
43
|
+
self[name] = nil
|
44
|
+
end
|
45
|
+
elsif another.respond_to?(:each_pair)
|
46
|
+
another.each_pair do |name, value|
|
47
|
+
self[name] = value
|
48
|
+
end
|
49
|
+
else
|
50
|
+
another.each do |name, value|
|
51
|
+
self[name] = value
|
52
|
+
end
|
53
|
+
end
|
54
|
+
self
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
def unstruct(value)
|
59
|
+
case value
|
60
|
+
when CStruct
|
61
|
+
value.to_h
|
62
|
+
when Array
|
63
|
+
value.collect do |v|
|
64
|
+
unstruct(v)
|
65
|
+
end
|
66
|
+
else
|
67
|
+
value
|
68
|
+
end
|
69
|
+
end
|
13
70
|
end
|
14
71
|
|
15
|
-
# C union
|
72
|
+
# A base class for objects representing a C union
|
16
73
|
class CUnion
|
17
74
|
# accessor to Fiddle::CUnionEntity
|
18
75
|
def CUnion.entity_class
|
@@ -20,6 +77,41 @@ module Fiddle
|
|
20
77
|
end
|
21
78
|
end
|
22
79
|
|
80
|
+
# Wrapper for arrays within a struct
|
81
|
+
class StructArray < Array
|
82
|
+
include ValueUtil
|
83
|
+
|
84
|
+
def initialize(ptr, type, initial_values)
|
85
|
+
@ptr = ptr
|
86
|
+
@type = type
|
87
|
+
@is_struct = @type.respond_to?(:entity_class)
|
88
|
+
if @is_struct
|
89
|
+
super(initial_values)
|
90
|
+
else
|
91
|
+
@size = Fiddle::PackInfo::SIZE_MAP[type]
|
92
|
+
@pack_format = Fiddle::PackInfo::PACK_MAP[type]
|
93
|
+
super(initial_values.collect { |v| unsigned_value(v, type) })
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def to_ptr
|
98
|
+
@ptr
|
99
|
+
end
|
100
|
+
|
101
|
+
def []=(index, value)
|
102
|
+
if index < 0 || index >= size
|
103
|
+
raise IndexError, 'index %d outside of array bounds 0...%d' % [index, size]
|
104
|
+
end
|
105
|
+
|
106
|
+
if @is_struct
|
107
|
+
self[index].replace(value)
|
108
|
+
else
|
109
|
+
to_ptr[index * @size, @size] = [value].pack(@pack_format)
|
110
|
+
super(index, value)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
23
115
|
# Used to construct C classes (CUnion, CStruct, etc)
|
24
116
|
#
|
25
117
|
# Fiddle::Importer#struct and Fiddle::Importer#union wrap this functionality in an
|
@@ -35,7 +127,7 @@ module Fiddle
|
|
35
127
|
# Fiddle::Importer#struct and Fiddle::Importer#union wrap this functionality in an
|
36
128
|
# easy-to-use manner.
|
37
129
|
#
|
38
|
-
#
|
130
|
+
# Examples:
|
39
131
|
#
|
40
132
|
# require 'fiddle/struct'
|
41
133
|
# require 'fiddle/cparser'
|
@@ -46,47 +138,98 @@ module Fiddle
|
|
46
138
|
#
|
47
139
|
# MyStruct = Fiddle::CStructBuilder.create(Fiddle::CUnion, types, members)
|
48
140
|
#
|
49
|
-
#
|
141
|
+
# MyStruct.malloc(Fiddle::RUBY_FREE) do |obj|
|
142
|
+
# ...
|
143
|
+
# end
|
144
|
+
#
|
145
|
+
# obj = MyStruct.malloc(Fiddle::RUBY_FREE)
|
146
|
+
# begin
|
147
|
+
# ...
|
148
|
+
# ensure
|
149
|
+
# obj.call_free
|
150
|
+
# end
|
151
|
+
#
|
152
|
+
# obj = MyStruct.malloc
|
153
|
+
# begin
|
154
|
+
# ...
|
155
|
+
# ensure
|
156
|
+
# Fiddle.free obj.to_ptr
|
157
|
+
# end
|
50
158
|
#
|
51
159
|
def create(klass, types, members)
|
52
160
|
new_class = Class.new(klass){
|
53
|
-
define_method(:initialize){|addr|
|
54
|
-
|
161
|
+
define_method(:initialize){|addr, func = nil|
|
162
|
+
if addr.is_a?(self.class.entity_class)
|
163
|
+
@entity = addr
|
164
|
+
else
|
165
|
+
@entity = self.class.entity_class.new(addr, types, func)
|
166
|
+
end
|
55
167
|
@entity.assign_names(members)
|
56
168
|
}
|
169
|
+
define_method(:[]) { |*args| @entity.send(:[], *args) }
|
170
|
+
define_method(:[]=) { |*args| @entity.send(:[]=, *args) }
|
57
171
|
define_method(:to_ptr){ @entity }
|
58
172
|
define_method(:to_i){ @entity.to_i }
|
173
|
+
define_singleton_method(:types) { types }
|
174
|
+
define_singleton_method(:members) { members }
|
59
175
|
members.each{|name|
|
176
|
+
name = name[0] if name.is_a?(Array) # name is a nested struct
|
177
|
+
next if method_defined?(name)
|
60
178
|
define_method(name){ @entity[name] }
|
61
179
|
define_method(name + "="){|val| @entity[name] = val }
|
62
180
|
}
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
181
|
+
entity_class = klass.entity_class
|
182
|
+
alignment = entity_class.alignment(types)
|
183
|
+
size = entity_class.size(types)
|
184
|
+
define_singleton_method(:alignment) { alignment }
|
185
|
+
define_singleton_method(:size) { size }
|
186
|
+
define_singleton_method(:malloc) do |func=nil, &block|
|
187
|
+
if block
|
188
|
+
entity_class.malloc(types, func, size) do |entity|
|
189
|
+
block.call(new(entity))
|
190
|
+
end
|
191
|
+
else
|
192
|
+
new(entity_class.malloc(types, func, size))
|
193
|
+
end
|
68
194
|
end
|
69
|
-
|
70
|
-
addr = Fiddle.malloc(#{size})
|
71
|
-
new(addr)
|
72
|
-
end
|
73
|
-
EOS
|
195
|
+
}
|
74
196
|
return new_class
|
75
197
|
end
|
76
198
|
module_function :create
|
77
199
|
end
|
78
200
|
|
79
|
-
# A C
|
201
|
+
# A pointer to a C structure
|
80
202
|
class CStructEntity < Fiddle::Pointer
|
81
203
|
include PackInfo
|
82
204
|
include ValueUtil
|
83
205
|
|
206
|
+
def CStructEntity.alignment(types)
|
207
|
+
max = 1
|
208
|
+
types.each do |type, count = 1|
|
209
|
+
if type.respond_to?(:entity_class)
|
210
|
+
n = type.alignment
|
211
|
+
else
|
212
|
+
n = ALIGN_MAP[type]
|
213
|
+
end
|
214
|
+
max = n if n > max
|
215
|
+
end
|
216
|
+
max
|
217
|
+
end
|
218
|
+
|
84
219
|
# Allocates a C struct with the +types+ provided.
|
85
220
|
#
|
86
|
-
#
|
87
|
-
def CStructEntity.malloc(types, func = nil)
|
88
|
-
|
89
|
-
|
221
|
+
# See Fiddle::Pointer.malloc for memory management issues.
|
222
|
+
def CStructEntity.malloc(types, func = nil, size = size(types), &block)
|
223
|
+
if block_given?
|
224
|
+
super(size, func) do |struct|
|
225
|
+
struct.set_ctypes types
|
226
|
+
yield struct
|
227
|
+
end
|
228
|
+
else
|
229
|
+
struct = super(size, func)
|
230
|
+
struct.set_ctypes types
|
231
|
+
struct
|
232
|
+
end
|
90
233
|
end
|
91
234
|
|
92
235
|
# Returns the offset for the packed sizes for the given +types+.
|
@@ -102,9 +245,15 @@ module Fiddle
|
|
102
245
|
max_align = types.map { |type, count = 1|
|
103
246
|
last_offset = offset
|
104
247
|
|
105
|
-
|
248
|
+
if type.respond_to?(:entity_class)
|
249
|
+
align = type.alignment
|
250
|
+
type_size = type.size
|
251
|
+
else
|
252
|
+
align = PackInfo::ALIGN_MAP[type]
|
253
|
+
type_size = PackInfo::SIZE_MAP[type]
|
254
|
+
end
|
106
255
|
offset = PackInfo.align(last_offset, align) +
|
107
|
-
(
|
256
|
+
(type_size * count)
|
108
257
|
|
109
258
|
align
|
110
259
|
}.max
|
@@ -118,13 +267,37 @@ module Fiddle
|
|
118
267
|
#
|
119
268
|
# See also Fiddle::Pointer.new
|
120
269
|
def initialize(addr, types, func = nil)
|
270
|
+
if func && addr.is_a?(Pointer) && addr.free
|
271
|
+
raise ArgumentError, 'free function specified on both underlying struct Pointer and when creating a CStructEntity - who do you want to free this?'
|
272
|
+
end
|
121
273
|
set_ctypes(types)
|
122
274
|
super(addr, @size, func)
|
123
275
|
end
|
124
276
|
|
125
277
|
# Set the names of the +members+ in this C struct
|
126
278
|
def assign_names(members)
|
127
|
-
@members =
|
279
|
+
@members = []
|
280
|
+
@nested_structs = {}
|
281
|
+
members.each_with_index do |member, index|
|
282
|
+
if member.is_a?(Array) # nested struct
|
283
|
+
member_name = member[0]
|
284
|
+
struct_type, struct_count = @ctypes[index]
|
285
|
+
if struct_count.nil?
|
286
|
+
struct = struct_type.new(to_i + @offset[index])
|
287
|
+
else
|
288
|
+
structs = struct_count.times.map do |i|
|
289
|
+
struct_type.new(to_i + @offset[index] + i * struct_type.size)
|
290
|
+
end
|
291
|
+
struct = StructArray.new(to_i + @offset[index],
|
292
|
+
struct_type,
|
293
|
+
structs)
|
294
|
+
end
|
295
|
+
@nested_structs[member_name] = struct
|
296
|
+
else
|
297
|
+
member_name = member
|
298
|
+
end
|
299
|
+
@members << member_name
|
300
|
+
end
|
128
301
|
end
|
129
302
|
|
130
303
|
# Calculates the offsets and sizes for the given +types+ in the struct.
|
@@ -135,12 +308,18 @@ module Fiddle
|
|
135
308
|
|
136
309
|
max_align = types.map { |type, count = 1|
|
137
310
|
orig_offset = offset
|
138
|
-
|
311
|
+
if type.respond_to?(:entity_class)
|
312
|
+
align = type.alignment
|
313
|
+
type_size = type.size
|
314
|
+
else
|
315
|
+
align = ALIGN_MAP[type]
|
316
|
+
type_size = SIZE_MAP[type]
|
317
|
+
end
|
139
318
|
offset = PackInfo.align(orig_offset, align)
|
140
319
|
|
141
320
|
@offset << offset
|
142
321
|
|
143
|
-
offset += (
|
322
|
+
offset += (type_size * count)
|
144
323
|
|
145
324
|
align
|
146
325
|
}.max
|
@@ -148,15 +327,34 @@ module Fiddle
|
|
148
327
|
@size = PackInfo.align(offset, max_align)
|
149
328
|
end
|
150
329
|
|
151
|
-
# Fetch struct member +name+
|
152
|
-
|
330
|
+
# Fetch struct member +name+ if only one argument is specified. If two
|
331
|
+
# arguments are specified, the first is an offset and the second is a
|
332
|
+
# length and this method returns the string of +length+ bytes beginning at
|
333
|
+
# +offset+.
|
334
|
+
#
|
335
|
+
# Examples:
|
336
|
+
#
|
337
|
+
# my_struct = struct(['int id']).malloc
|
338
|
+
# my_struct.id = 1
|
339
|
+
# my_struct['id'] # => 1
|
340
|
+
# my_struct[0, 4] # => "\x01\x00\x00\x00".b
|
341
|
+
#
|
342
|
+
def [](*args)
|
343
|
+
return super(*args) if args.size > 1
|
344
|
+
name = args[0]
|
153
345
|
idx = @members.index(name)
|
154
346
|
if( idx.nil? )
|
155
347
|
raise(ArgumentError, "no such member: #{name}")
|
156
348
|
end
|
157
349
|
ty = @ctypes[idx]
|
158
350
|
if( ty.is_a?(Array) )
|
159
|
-
|
351
|
+
if ty.first.respond_to?(:entity_class)
|
352
|
+
return @nested_structs[name]
|
353
|
+
else
|
354
|
+
r = super(@offset[idx], SIZE_MAP[ty[0]] * ty[1])
|
355
|
+
end
|
356
|
+
elsif ty.respond_to?(:entity_class)
|
357
|
+
return @nested_structs[name]
|
160
358
|
else
|
161
359
|
r = super(@offset[idx], SIZE_MAP[ty.abs])
|
162
360
|
end
|
@@ -176,14 +374,44 @@ module Fiddle
|
|
176
374
|
if( ty.is_a?(Integer) && (ty < 0) )
|
177
375
|
return unsigned_value(val, ty)
|
178
376
|
elsif( ty.is_a?(Array) && (ty[0] < 0) )
|
179
|
-
return
|
377
|
+
return StructArray.new(self + @offset[idx], ty[0], val)
|
180
378
|
else
|
181
379
|
return val
|
182
380
|
end
|
183
381
|
end
|
184
382
|
|
185
|
-
# Set struct member +name+, to value +val
|
186
|
-
|
383
|
+
# Set struct member +name+, to value +val+. If more arguments are
|
384
|
+
# specified, writes the string of bytes to the memory at the given
|
385
|
+
# +offset+ and +length+.
|
386
|
+
#
|
387
|
+
# Examples:
|
388
|
+
#
|
389
|
+
# my_struct = struct(['int id']).malloc
|
390
|
+
# my_struct['id'] = 1
|
391
|
+
# my_struct[0, 4] = "\x01\x00\x00\x00".b
|
392
|
+
# my_struct.id # => 1
|
393
|
+
#
|
394
|
+
def []=(*args)
|
395
|
+
return super(*args) if args.size > 2
|
396
|
+
name, val = *args
|
397
|
+
name = name.to_s if name.is_a?(Symbol)
|
398
|
+
nested_struct = @nested_structs[name]
|
399
|
+
if nested_struct
|
400
|
+
if nested_struct.is_a?(StructArray)
|
401
|
+
if val.nil?
|
402
|
+
nested_struct.each do |s|
|
403
|
+
s.replace(nil)
|
404
|
+
end
|
405
|
+
else
|
406
|
+
val.each_with_index do |v, i|
|
407
|
+
nested_struct[i] = v
|
408
|
+
end
|
409
|
+
end
|
410
|
+
else
|
411
|
+
nested_struct.replace(val)
|
412
|
+
end
|
413
|
+
return val
|
414
|
+
end
|
187
415
|
idx = @members.index(name)
|
188
416
|
if( idx.nil? )
|
189
417
|
raise(ArgumentError, "no such member: #{name}")
|
@@ -202,23 +430,16 @@ module Fiddle
|
|
202
430
|
end
|
203
431
|
end
|
204
432
|
|
433
|
+
undef_method :size=
|
205
434
|
def to_s() # :nodoc:
|
206
435
|
super(@size)
|
207
436
|
end
|
208
437
|
end
|
209
438
|
|
210
|
-
# A C union
|
439
|
+
# A pointer to a C union
|
211
440
|
class CUnionEntity < CStructEntity
|
212
441
|
include PackInfo
|
213
442
|
|
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
443
|
# Returns the size needed for the union with the given +types+.
|
223
444
|
#
|
224
445
|
# Fiddle::CUnionEntity.size(
|
@@ -228,7 +449,11 @@ module Fiddle
|
|
228
449
|
# Fiddle::TYPE_VOIDP ]) #=> 8
|
229
450
|
def CUnionEntity.size(types)
|
230
451
|
types.map { |type, count = 1|
|
231
|
-
|
452
|
+
if type.respond_to?(:entity_class)
|
453
|
+
type.size * count
|
454
|
+
else
|
455
|
+
PackInfo::SIZE_MAP[type] * count
|
456
|
+
end
|
232
457
|
}.max
|
233
458
|
end
|
234
459
|
|
@@ -241,4 +466,3 @@ module Fiddle
|
|
241
466
|
end
|
242
467
|
end
|
243
468
|
end
|
244
|
-
|