Skip to content

Commit 8e44eea

Browse files
committed
Fix Fiddle::Pointer#ref behavior for FFI backend
1 parent 8eab55b commit 8e44eea

File tree

2 files changed

+26
-11
lines changed

2 files changed

+26
-11
lines changed

lib/fiddle/ffi_backend.rb

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,6 @@ class DLError < Error; end
219219
class ClearedReferenceError < Error; end
220220

221221
class Pointer
222-
attr_reader :ffi_ptr
223222
extend FFI::DataConverter
224223
native_type FFI::Type::Builtin::POINTER
225224

@@ -285,15 +284,15 @@ def []=(*args, value)
285284
value = value.to_str(args[1])
286285
end
287286

288-
@ffi_ptr.put_bytes(args[0], value, 0, args[1])
287+
ffi_ptr.put_bytes(args[0], value, 0, args[1])
289288
elsif args.size == 1
290289
if value.is_a?(Fiddle::Pointer)
291290
value = value.to_str(args[0] + 1)
292291
else
293292
value = value.chr
294293
end
295294

296-
@ffi_ptr.put_bytes(args[0], value, 0, 1)
295+
ffi_ptr.put_bytes(args[0], value, 0, 1)
297296
end
298297
rescue FFI::NullPointerError
299298
raise DLError.new("NULL pointer access")
@@ -332,9 +331,14 @@ def initialize(addr, size = nil, free = nil)
332331
end
333332
@free = free
334333
@ffi_ptr = ptr
334+
@addr_ptr = nil
335335
@freed = false
336336
end
337337

338+
def ffi_ptr
339+
@addr_ptr ? @addr_ptr.get_pointer(0) : @ffi_ptr
340+
end
341+
338342
module LibC
339343
extend FFI::Library
340344
ffi_lib FFI::Library::LIBC
@@ -363,11 +367,11 @@ def self.malloc(size, free = nil)
363367
end
364368

365369
def null?
366-
@ffi_ptr.null?
370+
ffi_ptr.null?
367371
end
368372

369373
def to_ptr
370-
@ffi_ptr
374+
ffi_ptr
371375
end
372376

373377
def size
@@ -386,9 +390,9 @@ def call_free
386390
return if @free.nil?
387391
return if @freed
388392
if @free == RUBY_FREE
389-
LibC::FREE.call(@ffi_ptr)
393+
LibC::FREE.call(ffi_ptr)
390394
else
391-
@free.call(@ffi_ptr)
395+
@free.call(ffi_ptr)
392396
end
393397
@freed = true
394398
end
@@ -492,10 +496,8 @@ def -@
492496
end
493497

494498
def ref
495-
cptr = Pointer.malloc(FFI::Type::POINTER.size, RUBY_FREE)
496-
cptr.ffi_ptr.put_pointer(0, ffi_ptr)
497-
cptr.size = 0
498-
cptr
499+
@addr_ptr ||= FFI::MemoryPointer.new(:pointer).put_pointer(0, ffi_ptr)
500+
Pointer.new(@addr_ptr, 0)
499501
end
500502
end
501503

test/fiddle/test_pointer.rb

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,19 @@ def test_cmp
187187
assert_nil(ptr <=> 10, '10 should not be comparable')
188188
end
189189

190+
def test_ref
191+
ptr = Fiddle::Pointer["hello"]
192+
ref = ptr.ref
193+
assert_equal 0, ref.size
194+
assert_nil ref.free
195+
assert_equal ptr, ref.ptr
196+
197+
ptr2 = Fiddle::Pointer["world"]
198+
ptr.ref[0, Fiddle::SIZEOF_VOIDP] = ptr2.ref
199+
assert_equal "world", ptr.to_s
200+
assert_equal ptr.to_i, ptr2.to_i
201+
end
202+
190203
def test_ref_ptr
191204
if ffi_backend?
192205
omit("Fiddle.dlwrap([]) isn't supported with FFI backend")

0 commit comments

Comments
 (0)