[ruby/fiddle] ffi_backend: convert numeric function args to pointers

(https://github.com/ruby/fiddle/pull/162)

This allows for passing integers as pointer arguments to functions when
using the FFI backend. This is a workaround until we can get JRuby's FFI
implementation to allow for it directly (see also
https://github.com/jruby/jruby/pull/8423)

---------

https://github.com/ruby/fiddle/commit/e2f0952e9b

Co-authored-by: Benoit Daloze <eregontp@gmail.com>
This commit is contained in:
Dani Smith 2024-12-12 01:43:51 +02:00 committed by Hiroshi SHIBATA
parent cce7cffbd3
commit 7c260bd424
No known key found for this signature in database
GPG Key ID: F9CF13417264FAC2
3 changed files with 28 additions and 10 deletions

View File

@ -159,15 +159,16 @@ module Fiddle
args[i] = Fiddle::FFIBackend.to_ffi_type(args[i])
end
else
args.map! do |arg|
if arg.respond_to?(:to_ptr)
begin
arg = arg.to_ptr
end until arg.is_a?(FFI::Pointer) || !arg.respond_to?(:to_ptr)
arg
else
arg
end
@args.each_with_index do |arg_type, i|
next unless arg_type == Types::VOIDP
src = args[i]
next if src.nil?
next if src.is_a?(String)
next if src.is_a?(FFI::AbstractMemory)
next if src.is_a?(FFI::Struct)
args[i] = Pointer[src]
end
end
result = @function.call(*args, &block)
@ -316,6 +317,8 @@ module Fiddle
end
elsif addr.is_a?(IO)
raise NotImplementedError, "IO ptr isn't supported"
else
FFI::Pointer.new(Integer(addr))
end
@size = size ? size : ptr.size

View File

@ -98,6 +98,15 @@ module Fiddle
assert_in_delta 1.0, func.call(90 * Math::PI / 180), 0.0001
end
def test_integer_pointer_conversion
func = Function.new(@libc['memcpy'], [TYPE_VOIDP, TYPE_VOIDP, TYPE_SIZE_T], TYPE_VOIDP)
str = 'hello'
Pointer.malloc(str.bytesize, Fiddle::RUBY_FREE) do |dst|
func.call(dst.to_i, str, dst.size)
assert_equal(str, dst.to_str)
end
end
def test_argument_count
closure_class = Class.new(Closure) do
def call one

View File

@ -157,11 +157,17 @@ module Fiddle
end
end
def test_to_ptr_with_num
def test_to_ptr_with_int
ptr = Pointer.new 0
assert_equal ptr, Pointer[0]
end
MimicInteger = Struct.new(:to_int)
def test_to_ptr_with_to_int
ptr = Pointer.new 0
assert_equal ptr, Pointer[MimicInteger.new(0)]
end
def test_equals
ptr = Pointer.new 0
ptr2 = Pointer.new 0