Fiddle 模块
Ruby 的 libffi 包装器。
说明¶ ↑
Fiddle
是一个扩展,用于用 Ruby 翻译外来函数接口 (FFI)。
它包装了 libffi,这是一个流行的 C 库,它提供了一个可移植的接口,允许用一种语言编写的代码调用用另一种语言编写的代码。
示例¶ ↑
这里我们将使用 Fiddle::Function
来包装 libm 中的 floor(3)
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
常量
- ALIGN_BOOL
-
bool 的对齐大小
- ALIGN_CHAR
-
char 的对齐大小
- ALIGN_DOUBLE
-
double 的对齐大小
- ALIGN_FLOAT
-
float 的对齐大小
- ALIGN_INT
-
int 的对齐大小
- ALIGN_INT16_T
-
int16_t 的对齐大小
- ALIGN_INT32_T
-
int32_t 的对齐大小
- ALIGN_INT64_T
-
int64_t 的对齐大小
- ALIGN_INT8_T
-
int8_t 的对齐大小
- ALIGN_INTPTR_T
-
intptr_t 的对齐大小
- ALIGN_LONG
-
long 的对齐大小
- ALIGN_LONG_LONG
-
long long 的对齐大小
- ALIGN_PTRDIFF_T
-
ptrdiff_t 的对齐大小
- ALIGN_SHORT
-
short 的对齐大小
- ALIGN_SIZE_T
-
size_t 的对齐大小
- ALIGN_SSIZE_T
-
ssize_t 的对齐大小
- ALIGN_UINTPTR_T
-
uintptr_t 的对齐大小
- ALIGN_VOIDP
-
void* 的对齐大小
- BUILD_RUBY_PLATFORM
-
针对其构建的平台(例如“x86_64-linux”等)
另请参阅 RUBY_PLATFORM
- Qfalse
-
Qfalse
的值 - Qnil
-
Qnil
的值 - Qtrue
-
Qtrue
的值 - Qundef
-
Qundef
的值 - RUBY_FREE
-
ruby_xfree() 函数的地址
- SIZEOF_BOOL
-
bool 的大小
- SIZEOF_CHAR
-
char 的大小
- SIZEOF_CONST_STRING
-
const char* 的大小
- SIZEOF_DOUBLE
-
double 的大小
- SIZEOF_FLOAT
-
float 的大小
- SIZEOF_INT
-
int 的大小
- SIZEOF_INT16_T
-
int16_t 的大小
- SIZEOF_INT32_T
-
int32_t 的大小
- SIZEOF_INT64_T
-
int64_t 的大小
- SIZEOF_INT8_T
-
int8_t 的大小
- SIZEOF_INTPTR_T
-
intptr_t 的大小
- SIZEOF_LONG
-
long 的大小
- SIZEOF_LONG_LONG
-
long long 的大小
- SIZEOF_PTRDIFF_T
-
ptrdiff_t 的大小
- SIZEOF_SHORT
-
short 的大小
- SIZEOF_SIZE_T
-
size_t 的大小
- SIZEOF_SSIZE_T
-
ssize_t 的大小
- SIZEOF_UCHAR
-
unsigned char 的大小
- SIZEOF_UINT
-
unsigned int 的大小
- SIZEOF_UINT16_T
-
uint16_t 的大小
- SIZEOF_UINT32_T
-
uint32_t 的大小
- SIZEOF_UINT64_T
-
uint64_t 的大小
- SIZEOF_UINT8_T
-
uint8_t 的大小
- SIZEOF_UINTPTR_T
-
uintptr_t 的大小
- SIZEOF_ULONG
-
unsigned long 的大小
- SIZEOF_ULONG_LONG
-
unsigned long long 的大小
- SIZEOF_USHORT
-
unsigned short 的大小
- SIZEOF_VOIDP
-
void* 的大小
- VERSION
- WINDOWS
返回一个布尔值,表示主机是否是 WIN32
公共类方法
创建一个新的处理程序,打开 library
,并返回一个 Fiddle::Handle
实例。
如果为 library
指定 nil
,则使用 Fiddle::Handle::DEFAULT,它等效于 RTLD_DEFAULT。有关更多信息,请参见 man 3 dlopen
。
lib = Fiddle.dlopen(nil)
默认值取决于操作系统,并为所有已加载的库提供一个句柄。例如,在大多数情况下,你可以使用它来访问 libc
函数或 rb_str_new
等 ruby 函数。
有关更多信息,请参见 Fiddle::Handle.new
。
# 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
返回存储在内存地址 addr
中的 Ruby 对象
示例
x = Object.new # => #<Object:0x0000000107c7d870> Fiddle.dlwrap(x) # => 4425504880 Fiddle.dlunwrap(_) # => #<Object:0x0000000107c7d870>
VALUE rb_fiddle_ptr2value(VALUE self, VALUE addr) { return (VALUE)NUM2PTR(addr); }
返回存储在 val
中的 Ruby 对象的内存地址
示例
x = Object.new # => #<Object:0x0000000107c7d870> Fiddle.dlwrap(x) # => 4425504880
如果 val
不是堆分配对象,此方法将返回标记的指针值。
示例
Fiddle.dlwrap(123) # => 247
static VALUE rb_fiddle_value2ptr(VALUE self, VALUE val) { return PTR2NUM((void*)val); }
释放地址 addr
处的内存
VALUE rb_fiddle_free(VALUE self, VALUE addr) { void *ptr = NUM2PTR(addr); ruby_xfree(ptr); return Qnil; }
返回当前执行 Thread
的最后一个 Error
,如果没有则返回 nil
# File ext/fiddle/lib/fiddle.rb, line 35 def self.last_error Thread.current[:__FIDDLE_LAST_ERROR__] end
将当前执行 Thread
的最后一个 Error
设置为 error
# 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
分配 size
字节的内存并返回分配的内存的整数内存地址。
static VALUE rb_fiddle_malloc(VALUE self, VALUE size) { void *ptr; ptr = (void*)ruby_xcalloc(1, NUM2SIZET(size)); return PTR2NUM(ptr); }
将内存位置 addr
处分配的内存大小更改为 size
字节。返回重新分配的内存的内存地址,该地址可能与传入的地址不同。
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); }
返回当前执行 Thread
的最后一个 win32 Error
,如果没有则返回 nil
# File ext/fiddle/lib/fiddle.rb, line 12 def self.win32_last_error Thread.current[:__FIDDLE_WIN32_LAST_ERROR__] end
将当前执行 Thread
的最后一个 win32 Error
设置为 error
# File ext/fiddle/lib/fiddle.rb, line 17 def self.win32_last_error= error Thread.current[:__FIDDLE_WIN32_LAST_ERROR__] = error end
返回当前执行 Thread
的最后一个 win32 socket Error
,如果没有则返回 nil
# File ext/fiddle/lib/fiddle.rb, line 23 def self.win32_last_socket_error Thread.current[:__FIDDLE_WIN32_LAST_SOCKET_ERROR__] end
将当前执行 Thread
的最后一个 win32 socket Error
设置为 error
# File ext/fiddle/lib/fiddle.rb, line 29 def self.win32_last_socket_error= error Thread.current[:__FIDDLE_WIN32_LAST_SOCKET_ERROR__] = error end
私有实例方法
创建一个新的处理程序,打开 library
,并返回一个 Fiddle::Handle
实例。
如果为 library
指定 nil
,则使用 Fiddle::Handle::DEFAULT,它等效于 RTLD_DEFAULT。有关更多信息,请参见 man 3 dlopen
。
lib = Fiddle.dlopen(nil)
默认值取决于操作系统,并为所有已加载的库提供一个句柄。例如,在大多数情况下,你可以使用它来访问 libc
函数或 rb_str_new
等 ruby 函数。
有关更多信息,请参见 Fiddle::Handle.new
。
# 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