module Fiddle::Importer
DSL, предоставляющий средства для динамической загрузки библиотек и создания модулей на их основе, включая вызов внешних функций в загруженной библиотеке C.
Пример
require 'fiddle' require 'fiddle/import' module LibSum extend Fiddle::Importer dlload './libsum.so' extern 'double sum(double*, int)' extern 'double split(double)' end
Атрибуты
Открытые методы экземпляра
# File ext/fiddle/lib/fiddle/import.rb, line 237 def [](name) @func_map[name] end
Возвращает функцию, сопоставленную с name, созданную с помощью Fiddle::Importer.extern или Fiddle::Importer.bind
# File ext/fiddle/lib/fiddle/import.rb, line 193
def bind(signature, *opts, &blk)
name, ctype, argtype = parse_signature(signature, type_alias)
h = parse_bind_options(opts)
case h[:callback_type]
when :bind, nil
f = bind_function(name, ctype, argtype, h[:call_type], &blk)
else
raise(RuntimeError, "unknown callback type: #{h[:callback_type]}")
end
@func_map[name] = f
#define_method(name){|*args,&block| f.call(*args,&block)}
begin
/^(.+?):(\d+)/ =~ caller.first
file, line = $1, $2.to_i
rescue
file, line = __FILE__, __LINE__+3
end
module_eval(<<-EOS, file, line)
def #{name}(*args,&block)
@func_map['#{name}'].call(*args,&block)
end
EOS
module_function(name)
f
end Создаёт глобальный метод на основе заданной функции C signature, используя заданные opts в качестве параметров привязки и переданный блок.
# File ext/fiddle/lib/fiddle/import.rb, line 313
def bind_function(name, ctype, argtype, call_type = nil, &block)
abi = CALL_TYPE_TO_ABI[call_type]
closure = Class.new(Fiddle::Closure) {
define_method(:call, block)
}.new(ctype, argtype, abi)
Function.new(closure, argtype, ctype, abi, name: name)
end Возвращает новую обёртку-замыкание для функции name.
-
ctype— тип возвращаемого значения функции -
argtype—Arrayаргументов, передаваемых функции обратного вызова -
call_type— ABI замыкания -
blockпередаётся функции обратного вызова
См. Fiddle::Closure
# File ext/fiddle/lib/fiddle/import.rb, line 244
def create_value(ty, val=nil)
s = struct([ty + " value"])
ptr = s.malloc()
if( val )
ptr.value = val
end
return ptr
end Создаёт класс-обёртку для структуры C со значением ty
См. также Fiddle::Importer.struct
# File ext/fiddle/lib/fiddle/import.rb, line 76
def dlload(*libs)
handles = libs.collect{|lib|
case lib
when nil
nil
when Handle
lib
when Importer
lib.handlers
else
Fiddle.dlopen(lib)
end
}.flatten()
@handler = CompositeHandler.new(handles)
@func_map = {}
@type_alias = {}
end Создаёт массив обработчиков для заданных libs. Это может быть экземпляр Fiddle::Handle, Fiddle::Importer либо новый экземпляр Fiddle::Handle, созданный с помощью Fiddle.dlopen
Вызывает исключение DLError, если библиотеку не удаётся загрузить.
См. Fiddle.dlopen
# File ext/fiddle/lib/fiddle/import.rb, line 169
def extern(signature, *opts)
symname, ctype, argtype = parse_signature(signature, type_alias)
opt = parse_bind_options(opts)
f = import_function(symname, ctype, argtype, opt[:call_type])
name = symname.gsub(/@.+/,'')
@func_map[name] = f
# define_method(name){|*args,&block| f.call(*args,&block)}
begin
/^(.+?):(\d+)/ =~ caller.first
file, line = $1, $2.to_i
rescue
file, line = __FILE__, __LINE__+3
end
module_eval(<<-EOS, file, line)
def #{name}(*args, &block)
@func_map['#{name}'].call(*args,&block)
end
EOS
module_function(name)
f
end Создаёт глобальный метод на основе заданной функции C signature.
# File ext/fiddle/lib/fiddle/import.rb, line 266 def handler (@handler ||= nil) or raise "call dlload before importing symbols and functions" end
Экземпляр Fiddle::CompositeHandler
Вызывает ошибку, если нет открытых обработчиков.
# File ext/fiddle/lib/fiddle/import.rb, line 296
def import_function(name, ctype, argtype, call_type = nil)
addr = handler.sym(name)
if( !addr )
raise(DLError, "cannot find the function: #{name}()")
end
Function.new(addr, argtype, ctype, CALL_TYPE_TO_ABI[call_type],
name: name)
end Возвращает новый экземпляр Fiddle::Function по адресу в памяти заданной функции name.
Вызывает исключение DLError, если name не существует.
-
argtype—Arrayаргументов, передаваемых функцииname. -
ctype— тип возвращаемого значения функции -
call_type— ABI функции
См. также Fiddle:Function.new
См. Fiddle::CompositeHandler.sym и Fiddle::Handler.sym
# File ext/fiddle/lib/fiddle/import.rb, line 276
def import_symbol(name)
addr = handler.sym(name)
if( !addr )
raise(DLError, "cannot find the symbol: #{name}")
end
Pointer.new(addr)
end Возвращает новый экземпляр Fiddle::Pointer по адресу в памяти заданного символа name.
Вызывает исключение DLError, если name не существует.
# File ext/fiddle/lib/fiddle/import.rb, line 256 def import_value(ty, addr) s = struct([ty + " value"]) ptr = s.new(addr) return ptr end
Возвращает новый экземпляр структуры C со значением ty по адресу addr.
# File ext/fiddle/lib/fiddle/import.rb, line 101
def sizeof(ty)
case ty
when String
ty = parse_ctype(ty, type_alias).abs()
case ty
when TYPE_CHAR
return SIZEOF_CHAR
when TYPE_SHORT
return SIZEOF_SHORT
when TYPE_INT
return SIZEOF_INT
when TYPE_LONG
return SIZEOF_LONG
when TYPE_FLOAT
return SIZEOF_FLOAT
when TYPE_DOUBLE
return SIZEOF_DOUBLE
when TYPE_VOIDP
return SIZEOF_VOIDP
when TYPE_CONST_STRING
return SIZEOF_CONST_STRING
when TYPE_BOOL
return SIZEOF_BOOL
else
if defined?(TYPE_LONG_LONG) and
ty == TYPE_LONG_LONG
return SIZEOF_LONG_LONG
else
raise(DLError, "unknown type: #{ty}")
end
end
when Class
if( ty.instance_methods().include?(:to_ptr) )
return ty.size()
end
end
return Pointer[ty].size()
end Возвращает размер ty, используя Fiddle::Importer.parse_ctype для определения типа C и соответствующей константы Fiddle.
# File ext/fiddle/lib/fiddle/import.rb, line 222 def struct(signature) tys, mems = parse_struct_signature(signature, type_alias) Fiddle::CStructBuilder.create(CStruct, tys, mems) end
Создаёт класс-обёртку для структуры C, описанной в signature.
MyStruct = struct ['int i', 'char c']
# File ext/fiddle/lib/fiddle/import.rb, line 95 def typealias(alias_type, orig_type) @type_alias[alias_type] = orig_type end
Задаёт псевдоним типа для alias_type как orig_type
# File ext/fiddle/lib/fiddle/import.rb, line 230 def union(signature) tys, mems = parse_struct_signature(signature, type_alias) Fiddle::CStructBuilder.create(CUnion, tys, mems) end
Создаёт класс-обёртку для объединения C, описанного в signature.
MyUnion = union ['int i', 'char c']
Закрытые методы экземпляра
# File ext/fiddle/lib/fiddle/import.rb, line 140
def parse_bind_options(opts)
h = {}
while( opt = opts.shift() )
case opt
when :stdcall, :cdecl
h[:call_type] = opt
when :carried, :temp, :temporal, :bind
h[:callback_type] = opt
h[:carrier] = opts.shift()
else
h[opt] = true
end
end
h
end
Ruby Core © 1993–2025 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.