Class: Fiddle::Function
Relationships & Source Files | |
Inherits: | Object |
Defined in: | lib/fiddle/function.rb, ext/fiddle/pinned.c, lib/fiddle/ffi_backend.rb |
Overview
Description
A representation of a C function
Examples
‘strcpy’
@libc = Fiddle.dlopen "/lib/libc.so.6"
#=> #<Fiddle::Handle:0x00000001d7a8d8>
f = Fiddle::Function.new(
@libc['strcpy'],
[Fiddle::TYPE_VOIDP, Fiddle::TYPE_VOIDP],
Fiddle::TYPE_VOIDP)
#=> #<Fiddle::Function:0x00000001d8ee00>
buff = "000"
#=> "000"
str = f.call(buff, "123")
#=> #<Fiddle::Pointer:0x00000001d0c380 ptr=0x000000018a21b8 size=0 free=0x00000000000000>
str.to_s
#=> "123"
ABI check
@libc = Fiddle.dlopen "/lib/libc.so.6"
#=> #<Fiddle::Handle:0x00000001d7a8d8>
f = Fiddle::Function.new(@libc['strcpy'], [TYPE_VOIDP, TYPE_VOIDP], TYPE_VOIDP)
#=> #<Fiddle::Function:0x00000001d8ee00>
f.abi == Fiddle::Function::DEFAULT
#=> true
Constant Summary
-
DEFAULT =
# File 'lib/fiddle/ffi_backend.rb', line 122"default"
-
STDCALL =
# File 'lib/fiddle/ffi_backend.rb', line 123"stdcall"
Class Method Summary
Instance Attribute Summary
-
#abi
readonly
The ABI of the
Function
. -
#name
readonly
The name of this function.
-
#need_gvl? ⇒ Boolean
readonly
Whether GVL is needed to call this function.
-
#ptr
readonly
The address of this function.
Instance Method Summary
- #call(*args, &block)
-
#initialize(object) ⇒ Pinned
constructor
Alias for Closure#initialize.
-
#to_i
The integer memory location of this function.
-
#to_proc
Turn this function in to a proc.
Constructor Details
.new(ptr, args, return_type, abi = DEFAULT, kwargs = nil) ⇒ Function
# File 'lib/fiddle/ffi_backend.rb', line 125
def initialize(ptr, args, return_type, abi = DEFAULT, kwargs = nil) if kwargs.nil? if abi.kind_of? Hash kwargs = abi abi = DEFAULT end end @name = kwargs[:name] if kwargs.kind_of? Hash @ptr, @args, @return_type, @abi = ptr, args, return_type, abi raise TypeError.new "invalid argument types" unless args.is_a?(Array) ffi_return_type = Fiddle::FFIBackend.to_ffi_type(@return_type) ffi_args = @args.map { |t| Fiddle::FFIBackend.to_ffi_type(t) } pointer = FFI::Pointer.new(ptr.to_i) = {convention: @abi} if ffi_args.last == FFI::Type::Builtin::VARARGS @function = FFI::VariadicInvoker.new( pointer, ffi_args, ffi_return_type, ) else @function = FFI::Function.new(ffi_return_type, ffi_args, pointer, ) end end
#initialize(object) ⇒ Pinned
Alias for Closure#initialize. Create a new pinned object reference. The Pinned
instance will prevent the GC from moving object
.
Instance Attribute Details
#abi (readonly)
The ABI of the Function
.
# File 'lib/fiddle/function.rb', line 5
attr_reader :abi
#name (readonly)
The name of this function
# File 'lib/fiddle/function.rb', line 11
attr_reader :name
#need_gvl? ⇒ Boolean
(readonly)
Whether GVL is needed to call this function
# File 'lib/fiddle/function.rb', line 14
def need_gvl? @need_gvl end
#ptr (readonly)
The address of this function
# File 'lib/fiddle/function.rb', line 8
attr_reader :ptr
Instance Method Details
#call(*args, &block)
[ GitHub ]# File 'lib/fiddle/ffi_backend.rb', line 152
def call(*args, &block) if @function.is_a?(FFI::VariadicInvoker) n_fixed_args = @args.size - 1 n_fixed_args.step(args.size - 1, 2) do |i| if args[i] == :const_string || args[i] == Types::CONST_STRING args[i + 1] = String.try_convert(args[i + 1]) || args[i + 1] end args[i] = Fiddle::FFIBackend.to_ffi_type(args[i]) end else @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) result = Pointer.new(result) if result.is_a?(FFI::Pointer) result end
#to_i
The integer memory location of this function
# File 'lib/fiddle/function.rb', line 19
def to_i ptr.to_i end
#to_proc
Turn this function in to a proc
# File 'lib/fiddle/function.rb', line 24
def to_proc this = self lambda { |*args| this.call(*args) } end