Module: Fiddle
- Included in:
- Importer
- Defined in:
- ext/fiddle/fiddle.c,
lib/fiddle.rb,
lib/fiddle/pack.rb,
lib/fiddle/types.rb,
lib/fiddle/value.rb,
lib/fiddle/import.rb,
lib/fiddle/struct.rb,
lib/fiddle/closure.rb,
lib/fiddle/cparser.rb,
lib/fiddle/version.rb,
lib/fiddle/function.rb,
lib/fiddle/ffi_backend.rb,
ext/fiddle/fiddle.c,
ext/fiddle/closure.c
Overview
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
Defined Under Namespace
Modules: BasicTypes, CParser, CStructBuilder, FFIBackend, Importer, PackInfo, Types, ValueUtil, Win32Types Classes: CStruct, CStructEntity, CUnion, CUnionEntity, ClearedReferenceError, Closure, CompositeHandler, DLError, Error, Function, Handle, MemoryView, Packer, Pinned, Pointer, StructArray
Constant Summary collapse
- RTLD_GLOBAL =
Add constants for backwards compat
Handle::RTLD_GLOBAL
- RTLD_LAZY =
:nodoc:
Handle::RTLD_LAZY
- RTLD_NOW =
:nodoc:
Handle::RTLD_NOW
- VERSION =
"1.1.6"
- WINDOWS =
Qfalse
- RUBY_FREE =
Address of the ruby_xfree() function
PTR2NUM(ruby_xfree)
- NULL =
A NULL pointer
rb_fiddle_ptr_new(0, 0, 0)
- ALIGN_VOIDP =
The alignment size of a void*
INT2NUM(ALIGN_VOIDP)
- ALIGN_CHAR =
The alignment size of a char
INT2NUM(ALIGN_CHAR)
- ALIGN_SHORT =
The alignment size of a short
INT2NUM(ALIGN_SHORT)
- ALIGN_INT =
The alignment size of an int
INT2NUM(ALIGN_INT)
- ALIGN_LONG =
The alignment size of a long
INT2NUM(ALIGN_LONG)
- ALIGN_LONG_LONG =
The alignment size of a long long
INT2NUM(ALIGN_LONG_LONG)
- ALIGN_INT8_T =
The alignment size of a int8_t
INT2NUM(ALIGN_INT8_T)
- ALIGN_INT16_T =
The alignment size of a int16_t
INT2NUM(ALIGN_INT16_T)
- ALIGN_INT32_T =
The alignment size of a int32_t
INT2NUM(ALIGN_INT32_T)
- ALIGN_INT64_T =
The alignment size of a int64_t
INT2NUM(ALIGN_INT64_T)
- ALIGN_FLOAT =
The alignment size of a float
INT2NUM(ALIGN_FLOAT)
- ALIGN_DOUBLE =
The alignment size of a double
INT2NUM(ALIGN_DOUBLE)
- ALIGN_BOOL =
The alignment size of a bool
INT2NUM(ALIGN_OF(bool))
- ALIGN_SIZE_T =
The alignment size of a size_t
INT2NUM(ALIGN_OF(size_t))
- ALIGN_SSIZE_T =
same as size_t
INT2NUM(ALIGN_OF(size_t))
- ALIGN_PTRDIFF_T =
The alignment size of a ptrdiff_t
INT2NUM(ALIGN_OF(ptrdiff_t))
- ALIGN_INTPTR_T =
The alignment size of a intptr_t
INT2NUM(ALIGN_OF(intptr_t))
- ALIGN_UINTPTR_T =
The alignment size of a uintptr_t
INT2NUM(ALIGN_OF(uintptr_t))
- SIZEOF_VOIDP =
size of a void*
INT2NUM(sizeof(void*))
- SIZEOF_CHAR =
size of a char
INT2NUM(sizeof(char))
- SIZEOF_UCHAR =
size of a unsigned char
INT2NUM(sizeof(unsigned char))
- SIZEOF_SHORT =
size of a short
INT2NUM(sizeof(short))
- SIZEOF_USHORT =
size of a unsigned short
INT2NUM(sizeof(unsigned short))
- SIZEOF_INT =
size of an int
INT2NUM(sizeof(int))
- SIZEOF_UINT =
size of an unsigned int
INT2NUM(sizeof(unsigned int))
- SIZEOF_LONG =
size of a long
INT2NUM(sizeof(long))
- SIZEOF_ULONG =
size of a unsigned long
INT2NUM(sizeof(unsigned long))
- SIZEOF_LONG_LONG =
size of a long long
INT2NUM(sizeof(LONG_LONG))
- SIZEOF_ULONG_LONG =
size of a unsigned long long
INT2NUM(sizeof(unsigned LONG_LONG))
- SIZEOF_INT8_T =
size of a int8_t
INT2NUM(sizeof(int8_t))
- SIZEOF_UINT8_T =
size of a uint8_t
INT2NUM(sizeof(uint8_t))
- SIZEOF_INT16_T =
size of a int16_t
INT2NUM(sizeof(int16_t))
- SIZEOF_UINT16_T =
size of a uint16_t
INT2NUM(sizeof(uint16_t))
- SIZEOF_INT32_T =
size of a int32_t
INT2NUM(sizeof(int32_t))
- SIZEOF_UINT32_T =
size of a uint32_t
INT2NUM(sizeof(uint32_t))
- SIZEOF_INT64_T =
size of a int64_t
INT2NUM(sizeof(int64_t))
- SIZEOF_UINT64_T =
size of a uint64_t
INT2NUM(sizeof(uint64_t))
- SIZEOF_FLOAT =
size of a float
INT2NUM(sizeof(float))
- SIZEOF_DOUBLE =
size of a double
INT2NUM(sizeof(double))
- SIZEOF_BOOL =
size of a bool
INT2NUM(sizeof(bool))
- SIZEOF_SIZE_T =
size of a size_t
INT2NUM(sizeof(size_t))
- SIZEOF_SSIZE_T =
same as size_t
INT2NUM(sizeof(size_t))
- SIZEOF_PTRDIFF_T =
size of a ptrdiff_t
INT2NUM(sizeof(ptrdiff_t))
- SIZEOF_INTPTR_T =
size of a intptr_t
INT2NUM(sizeof(intptr_t))
- SIZEOF_UINTPTR_T =
size of a uintptr_t
INT2NUM(sizeof(uintptr_t))
- SIZEOF_CONST_STRING =
size of a const char*
INT2NUM(sizeof(const char*))
- BUILD_RUBY_PLATFORM =
Platform built against (i.e. “x86_64-linux”, etc.)
See also RUBY_PLATFORM
rb_str_new2(RUBY_PLATFORM)
- Qtrue =
The value of Qtrue
INT2NUM(Qtrue)
- Qfalse =
The value of Qfalse
INT2NUM(Qfalse)
- Qnil =
The value of Qnil
INT2NUM(Qnil)
- Qundef =
The value of Qundef
INT2NUM(Qundef)
Class Method Summary collapse
-
.dlopen(library) ⇒ Object
call-seq: dlopen(library) => Fiddle::Handle.
-
.dlunwrap(addr) ⇒ Object
Returns the Ruby object stored at the memory address
addr
. -
.dlwrap(val) ⇒ Object
Returns the memory address of the Ruby object stored at
val
. -
.free(addr) ⇒ Object
Free the memory at address
addr
. -
.last_error ⇒ Object
Returns the last
Error
of the current executingThread
or nil if none. -
.last_error=(error) ⇒ Object
Sets the last
Error
of the current executingThread
toerror
. -
.malloc(size) ⇒ Object
Allocate
size
bytes of memory and return the integer memory address for the allocated memory. -
.realloc(addr, size) ⇒ Object
Change the size of the memory allocated at the memory location
addr
tosize
bytes. -
.win32_last_error ⇒ Object
Returns the last win32
Error
of the current executingThread
or nil if none. -
.win32_last_error=(error) ⇒ Object
Sets the last win32
Error
of the current executingThread
toerror
. -
.win32_last_socket_error ⇒ Object
Returns the last win32 socket
Error
of the current executingThread
or nil if none. -
.win32_last_socket_error=(error) ⇒ Object
Sets the last win32 socket
Error
of the current executingThread
toerror
.
Class Method Details
.dlopen(library) ⇒ Object
call-seq: dlopen(library) => Fiddle::Handle
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.
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/fiddle.rb', line 91 def dlopen library begin Fiddle::Handle.new(library) rescue DLError => error case RUBY_PLATFORM when /linux/ case error. 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? first_input = $1 if first_input.start_with?("-l") first_input = "lib#{first_input[2..-1]}.so" end return dlopen(first_input) end end end # Not found raise end end |
.dlunwrap(addr) ⇒ Object
74 75 76 77 78 |
# File 'ext/fiddle/fiddle.c', line 74
VALUE
rb_fiddle_ptr2value(VALUE self, VALUE addr)
{
return (VALUE)NUM2PTR(addr);
}
|
.dlwrap(val) ⇒ Object
100 101 102 |
# File 'ext/fiddle/fiddle.c', line 100 def self.dlwrap(val) Pointer.to_ptr(val) end |
.free(addr) ⇒ Object
Free the memory at address addr
51 52 53 54 |
# File 'ext/fiddle/fiddle.c', line 51 def self.free(ptr) Fiddle::Pointer::LibC::FREE.call(ptr) nil end |
.last_error ⇒ Object
Returns the last Error
of the current executing Thread
or nil if none
57 58 59 60 61 62 63 64 |
# File 'lib/fiddle.rb', line 57 def self.last_error if RUBY_ENGINE == 'jruby' errno = FFI.errno errno == 0 ? nil : errno else Thread.current[:__FIDDLE_LAST_ERROR__] end end |
.last_error=(error) ⇒ Object
Sets the last Error
of the current executing Thread
to error
67 68 69 70 71 72 73 74 |
# File 'lib/fiddle.rb', line 67 def self.last_error= error if RUBY_ENGINE == 'jruby' FFI.errno = error || 0 else Thread.current[:__DL2_LAST_ERROR__] = error Thread.current[:__FIDDLE_LAST_ERROR__] = error end end |
.malloc(size) ⇒ Object
Allocate size
bytes of memory and return the integer memory address for the allocated memory.
22 23 24 |
# File 'ext/fiddle/fiddle.c', line 22 def self.malloc(size) Fiddle::Pointer.malloc(size) end |
.realloc(addr, size) ⇒ Object
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.
37 38 39 40 41 42 43 44 |
# File 'ext/fiddle/fiddle.c', line 37
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);
}
|
.win32_last_error ⇒ Object
Returns the last win32 Error
of the current executing Thread
or nil if none
16 17 18 19 20 21 22 23 |
# File 'lib/fiddle.rb', line 16 def self.win32_last_error if RUBY_ENGINE == 'jruby' errno = FFI.errno errno == 0 ? nil : errno else Thread.current[:__FIDDLE_WIN32_LAST_ERROR__] end end |
.win32_last_error=(error) ⇒ Object
Sets the last win32 Error
of the current executing Thread
to error
26 27 28 29 30 31 32 |
# File 'lib/fiddle.rb', line 26 def self.win32_last_error= error if RUBY_ENGINE == 'jruby' FFI.errno = error || 0 else Thread.current[:__FIDDLE_WIN32_LAST_ERROR__] = error end end |
.win32_last_socket_error ⇒ Object
Returns the last win32 socket Error
of the current executing Thread
or nil if none
36 37 38 39 40 41 42 43 |
# File 'lib/fiddle.rb', line 36 def self.win32_last_socket_error if RUBY_ENGINE == 'jruby' errno = FFI.errno errno == 0 ? nil : errno else Thread.current[:__FIDDLE_WIN32_LAST_SOCKET_ERROR__] end end |
.win32_last_socket_error=(error) ⇒ Object
Sets the last win32 socket Error
of the current executing Thread
to error
47 48 49 50 51 52 53 |
# File 'lib/fiddle.rb', line 47 def self.win32_last_socket_error= error if RUBY_ENGINE == 'jruby' FFI.errno = error || 0 else Thread.current[:__FIDDLE_WIN32_LAST_SOCKET_ERROR__] = error end end |