Module: Fiddle

Included in:
Importer
Defined in:
ext/fiddle/fiddle.c,
ext/fiddle/fiddle.c,
ext/fiddle/closure.c,
ext/fiddle/lib/fiddle.rb,
ext/fiddle/lib/fiddle/pack.rb,
ext/fiddle/lib/fiddle/types.rb,
ext/fiddle/lib/fiddle/value.rb,
ext/fiddle/lib/fiddle/import.rb,
ext/fiddle/lib/fiddle/struct.rb,
ext/fiddle/lib/fiddle/closure.rb,
ext/fiddle/lib/fiddle/cparser.rb,
ext/fiddle/lib/fiddle/version.rb,
ext/fiddle/lib/fiddle/function.rb

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, 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

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_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))
ALIGN_BOOL =

The alignment size of a bool

INT2NUM(ALIGN_OF(bool))
WINDOWS =
Qfalse
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_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*))
SIZEOF_BOOL =

size of a bool

INT2NUM(sizeof(bool))
RUBY_FREE =

Address of the ruby_xfree() function

PTR2NUM(ruby_xfree)
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)
NULL =

A NULL pointer

rb_fiddle_ptr_new(0, 0, 0)
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.3"

Class Method Summary collapse

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.



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File '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

.dlunwrap(addr) ⇒ Object

Returns the Ruby object stored at the memory address addr

Example:

x = Object.new
# => #<Object:0x0000000107c7d870>
Fiddle.dlwrap(x)
# => 4425504880
Fiddle.dlunwrap(_)
# => #<Object:0x0000000107c7d870>


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

Returns the memory address of the Ruby object stored at val

Example:

x = Object.new
# => #<Object:0x0000000107c7d870>
Fiddle.dlwrap(x)
# => 4425504880

In the case val is not a heap allocated object, this method will return the tagged pointer value.

Example:

Fiddle.dlwrap(123)
# => 247


100
101
102
103
104
# File 'ext/fiddle/fiddle.c', line 100

static VALUE
rb_fiddle_value2ptr(VALUE self, VALUE val)
{
    return PTR2NUM((void*)val);
}

.free(addr) ⇒ Object

Free the memory at address addr



51
52
53
54
55
56
57
58
# File 'ext/fiddle/fiddle.c', line 51

VALUE
rb_fiddle_free(VALUE self, VALUE addr)
{
    void *ptr = NUM2PTR(addr);

    ruby_xfree(ptr);
    return Qnil;
}

.last_errorObject

Returns the last Error of the current executing Thread or nil if none



35
36
37
# File 'ext/fiddle/lib/fiddle.rb', line 35

def self.last_error
  Thread.current[:__FIDDLE_LAST_ERROR__]
end

.last_error=(error) ⇒ Object

Sets the last Error of the current executing Thread to error



40
41
42
43
# File '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

.malloc(size) ⇒ Object

Allocate size bytes of memory and return the integer memory address for the allocated memory.



22
23
24
25
26
27
28
# File 'ext/fiddle/fiddle.c', line 22

static VALUE
rb_fiddle_malloc(VALUE self, VALUE size)
{
    void *ptr;
    ptr = (void*)ruby_xcalloc(1, NUM2SIZET(size));
    return PTR2NUM(ptr);
}

.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_errorObject

Returns the last win32 Error of the current executing Thread or nil if none



12
13
14
# File 'ext/fiddle/lib/fiddle.rb', line 12

def self.win32_last_error
  Thread.current[:__FIDDLE_WIN32_LAST_ERROR__]
end

.win32_last_error=(error) ⇒ Object

Sets the last win32 Error of the current executing Thread to error



17
18
19
# File 'ext/fiddle/lib/fiddle.rb', line 17

def self.win32_last_error= error
  Thread.current[:__FIDDLE_WIN32_LAST_ERROR__] = error
end

.win32_last_socket_errorObject

Returns the last win32 socket Error of the current executing Thread or nil if none



23
24
25
# File 'ext/fiddle/lib/fiddle.rb', line 23

def self.win32_last_socket_error
  Thread.current[:__FIDDLE_WIN32_LAST_SOCKET_ERROR__]
end

.win32_last_socket_error=(error) ⇒ Object

Sets the last win32 socket Error of the current executing Thread to error



29
30
31
# File 'ext/fiddle/lib/fiddle.rb', line 29

def self.win32_last_socket_error= error
  Thread.current[:__FIDDLE_WIN32_LAST_SOCKET_ERROR__] = error
end