A libffi wrapper for Ruby.
Description
Fiddle
is an extension to translate a foreign function interface (FFI) with ruby.
It wraps libffi, a popular C library which provides a portable interface that allows code written in one language to call code written in another language.
Example
Here we will use Fiddle::Function
to wrap floor(3) from libm
require 'fiddle' libm = Fiddle.dlopen('/lib/libm.so.6') floor = Fiddle::Function.new( libm['floor'], [Fiddle::TYPE_DOUBLE], Fiddle::TYPE_DOUBLE ) puts floor.call(3.14159) #=> 3.0
The alignment size of a void*
The alignment size of a char
The alignment size of a short
The alignment size of a long
The alignment size of a long long
The alignment size of a int8_t
The alignment size of a int16_t
The alignment size of a int32_t
The alignment size of a int64_t
The alignment size of a float
The alignment size of a double
The alignment size of a size_t
The alignment size of a ssize_t
The alignment size of a ptrdiff_t
The alignment size of a intptr_t
The alignment size of a uintptr_t
Returns a boolean regarding whether the host is WIN32
size of a void*
size of a char
size of a unsigned char
size of a short
size of a unsigned short
size of an int
size of an unsigned int
size of a long
size of a unsigned long
size of a long long
size of a unsigned long long
size of a int8_t
size of a uint8_t
size of a int16_t
size of a uint16_t
size of a int32_t
size of a uint32_t
size of a int64_t
size of a uint64_t
size of a float
size of a double
size of a size_t
size of a ssize_t
size of a ptrdiff_t
size of a intptr_t
size of a uintptr_t
size of a const char*
Add constants for backwards compat
# File tmp/rubies/ruby-3.2.0/ext/fiddle/lib/fiddle.rb, line 60
def dlopen library
begin
Fiddle::Handle.new(library)
rescue DLError => error
case RUBY_PLATFORM
when /linux/
case error.message
when /\A(\/.+?): (?:invalid ELF header|file too short)/
# This may be a linker script:
# https://sourceware.org/binutils/docs/ld.html#Scripts
path = $1
else
raise
end
else
raise
end
File.open(path) do |input|
input.each_line do |line|
case line
when /\A\s*(?:INPUT|GROUP)\s*\(\s*([^\s,\)]+)/
# TODO: Should we support multiple files?
return dlopen($1)
end
end
end
# Not found
raise
end
end
Creates a new handler that opens library
, and returns an instance of Fiddle::Handle
.
If nil
is given for the library
, Fiddle::Handle::DEFAULT is used, which is the equivalent to RTLD_DEFAULT. See man 3 dlopen
for more.
lib = Fiddle.dlopen(nil)
The default is dependent on OS, and provide a handle for all libraries already loaded. For example, in most cases you can use this to access libc
functions, or ruby functions like rb_str_new
.
See Fiddle::Handle.new
for more.
VALUE
rb_fiddle_ptr2value(VALUE self, VALUE addr)
{
return (VALUE)NUM2PTR(addr);
}
Returns the hexadecimal representation of a memory pointer address addr
Example:
lib = Fiddle.dlopen('/lib64/libc-2.15.so') => #<Fiddle::Handle:0x00000001342460> lib['strcpy'].to_s(16) => "7f59de6dd240" Fiddle.dlunwrap(Fiddle.dlwrap(lib['strcpy'].to_s(16))) => "7f59de6dd240"
static VALUE
rb_fiddle_value2ptr(VALUE self, VALUE val)
{
return PTR2NUM((void*)val);
}
Returns a memory pointer of a function’s hexadecimal address location val
Example:
lib = Fiddle.dlopen('/lib64/libc-2.15.so') => #<Fiddle::Handle:0x00000001342460> Fiddle.dlwrap(lib['strcpy'].to_s(16)) => 25522520
VALUE
rb_fiddle_free(VALUE self, VALUE addr)
{
void *ptr = NUM2PTR(addr);
ruby_xfree(ptr);
return Qnil;
}
Free the memory at address addr
# File tmp/rubies/ruby-3.2.0/ext/fiddle/lib/fiddle.rb, line 35
def self.last_error
Thread.current[:__FIDDLE_LAST_ERROR__]
end
Returns the last Error
of the current executing Thread
or nil if none
# File tmp/rubies/ruby-3.2.0/ext/fiddle/lib/fiddle.rb, line 40
def self.last_error= error
Thread.current[:__DL2_LAST_ERROR__] = error
Thread.current[:__FIDDLE_LAST_ERROR__] = error
end
Sets the last Error
of the current executing Thread
to error
static VALUE
rb_fiddle_malloc(VALUE self, VALUE size)
{
void *ptr;
ptr = (void*)ruby_xcalloc(1, NUM2SIZET(size));
return PTR2NUM(ptr);
}
Allocate size
bytes of memory and return the integer memory address for the allocated memory.
static VALUE
rb_fiddle_realloc(VALUE self, VALUE addr, VALUE size)
{
void *ptr = NUM2PTR(addr);
ptr = (void*)ruby_xrealloc(ptr, NUM2SIZET(size));
return PTR2NUM(ptr);
}
Change the size of the memory allocated at the memory location addr
to size
bytes. Returns the memory address of the reallocated memory, which may be different than the address passed in.
# File tmp/rubies/ruby-3.2.0/ext/fiddle/lib/fiddle.rb, line 12
def self.win32_last_error
Thread.current[:__FIDDLE_WIN32_LAST_ERROR__]
end
Returns the last win32 Error
of the current executing Thread
or nil if none
# File tmp/rubies/ruby-3.2.0/ext/fiddle/lib/fiddle.rb, line 17
def self.win32_last_error= error
Thread.current[:__FIDDLE_WIN32_LAST_ERROR__] = error
end
Sets the last win32 Error
of the current executing Thread
to error
# File tmp/rubies/ruby-3.2.0/ext/fiddle/lib/fiddle.rb, line 23
def self.win32_last_socket_error
Thread.current[:__FIDDLE_WIN32_LAST_SOCKET_ERROR__]
end
Returns the last win32 socket Error
of the current executing Thread
or nil if none
# File tmp/rubies/ruby-3.2.0/ext/fiddle/lib/fiddle.rb, line 29
def self.win32_last_socket_error= error
Thread.current[:__FIDDLE_WIN32_LAST_SOCKET_ERROR__] = error
end
Sets the last win32 socket Error
of the current executing Thread
to error
# File tmp/rubies/ruby-3.2.0/ext/fiddle/lib/fiddle.rb, line 60
def dlopen library
begin
Fiddle::Handle.new(library)
rescue DLError => error
case RUBY_PLATFORM
when /linux/
case error.message
when /\A(\/.+?): (?:invalid ELF header|file too short)/
# This may be a linker script:
# https://sourceware.org/binutils/docs/ld.html#Scripts
path = $1
else
raise
end
else
raise
end
File.open(path) do |input|
input.each_line do |line|
case line
when /\A\s*(?:INPUT|GROUP)\s*\(\s*([^\s,\)]+)/
# TODO: Should we support multiple files?
return dlopen($1)
end
end
end
# Not found
raise
end
end
Creates a new handler that opens library
, and returns an instance of Fiddle::Handle
.
If nil
is given for the library
, Fiddle::Handle::DEFAULT is used, which is the equivalent to RTLD_DEFAULT. See man 3 dlopen
for more.
lib = Fiddle.dlopen(nil)
The default is dependent on OS, and provide a handle for all libraries already loaded. For example, in most cases you can use this to access libc
functions, or ruby functions like rb_str_new
.
See Fiddle::Handle.new
for more.