Fiddle::Importer
module Fiddle::Importer
Included modules:Fiddle, Fiddle::CParser
一个DSL提供了动态加载库和构建模块的方法,包括调用已加载的C库中的extern函数。
例
require 'fiddle'
require 'fiddle/import'
module LibSum
extend Fiddle::Importer
dlload './libsum.so'
extern 'double sum(double*, int)'
extern 'double split(double)'
end
属性
type_aliasR
公共实例方法
Show source
返回映射到名称的函数,该函数由#extern或#bind创建
# File ext/fiddle/lib/fiddle/import.rb, line 232
def [](name)
@func_map[name]
end
bind(signature, *opts, &blk) Show source
使用给定的opts作为给定块的绑定参数,从给定的C signature
# File ext/fiddle/lib/fiddle/import.rb, line 188
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(" def #{name}(*args,&block)
@func_map['#{name}'].call(*args,&block)
end
", file, line)
module_function(name)
f
end
bind_function(name, ctype, argtype, call_type = nil, &block) Show source
为name
函数返回一个新的封闭包装。
ctype
是函数的返回类型
argtype
是一个传递给回调函数的参数数组
call_type
是关闭的abi
block
传递给回调
See Fiddle::Closure
# File ext/fiddle/lib/fiddle/import.rb, line 308
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
create_value(ty, val=nil) Show source
创建一个类来包装具有值ty的C结构
另见#struct
# File ext/fiddle/lib/fiddle/import.rb, line 239
def create_value(ty, val=nil)
s = struct([ty + " value"])
ptr = s.malloc()
if( val )
ptr.value = val
end
return ptr
end
别名:值
dlload(*libs) Show source
为给定的数组创建一个处理程序数组libs
,可以是Fiddle :: Handle,Fiddle :: Importer的一个实例,或者将使用Fiddle#dlopen创建Fiddle :: Handle的新实例
如果库无法加载,则引发DLError。
请参阅Fiddle#dlopen
# File ext/fiddle/lib/fiddle/import.rb, line 75
def dlload(*libs)
handles = libs.collect{|lib|
case lib
when nil
nil
when Handle
lib
when Importer
lib.handlers
else
begin
Fiddle.dlopen(lib)
rescue DLError
raise(DLError, "can't load #{lib}")
end
end
}.flatten()
@handler = CompositeHandler.new(handles)
@func_map = {}
@type_alias = {}
end
extern(signature, *opts) Show source
根据给定的C signature创建一个全局方法。
# File ext/fiddle/lib/fiddle/import.rb, line 164
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(" def #{name}(*args, &block)
@func_map['#{name}'].call(*args,&block)
end
", file, line)
module_function(name)
f
end
handler() Show source
The Fiddle::CompositeHandler instance
如果没有处理程序处于打开状态,则会引发错误。
# File ext/fiddle/lib/fiddle/import.rb, line 261
def handler
(@handler ||= nil) or raise "call dlload before importing symbols and functions"
end
import_function(name, ctype, argtype, call_type = nil) Show source
在给定name函数的内存地址返回一个新的Fiddle :: Function实例。
如果name
不存在,则引发DLError 。
argtype
是传递给name
函数的一个参数数组。
ctype
是函数的返回类型
call_type
是函数的ABI
另请参见Fiddle:Function.new
请参阅Fiddle :: CompositeHandler#sym 和 Fiddle :: Handler.sym
# File ext/fiddle/lib/fiddle/import.rb, line 291
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
import_symbol(name) Show source
在给定名称符号的内存地址返回一个新的Fiddle :: Pointer实例。
如果name
不存在,则引发DLError 。
请参阅Fiddle :: CompositeHandler#sym 和 Fiddle :: Handle.sym
# File ext/fiddle/lib/fiddle/import.rb, line 271
def import_symbol(name)
addr = handler.sym(name)
if( !addr )
raise(DLError, "cannot find the symbol: #{name}")
end
Pointer.new(addr)
end
import_value(ty, addr) Show source
返回地址为addr的值为ty的C结构的新实例。
# File ext/fiddle/lib/fiddle/import.rb, line 251
def import_value(ty, addr)
s = struct([ty + " value"])
ptr = s.new(addr)
return ptr
end
sizeof(ty) Show source
返回sizeof ty,使用Fiddle :: CParser#parse_ctype来确定C类型和适当的Fiddle常量。
# File ext/fiddle/lib/fiddle/import.rb, line 104
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_LONG_LONG
return SIZEOF_LONG_LONG
when TYPE_FLOAT
return SIZEOF_FLOAT
when TYPE_DOUBLE
return SIZEOF_DOUBLE
when TYPE_VOIDP
return SIZEOF_VOIDP
else
raise(DLError, "unknown type: #{ty}")
end
when Class
if( ty.instance_methods().include?(:to_ptr) )
return ty.size()
end
end
return Pointer[ty].size()
end
struct(signature) Show source
创建一个类来包装由signature描述的C结构。
MyStruct = struct ['int i', 'char c']
# File ext/fiddle/lib/fiddle/import.rb, line 217
def struct(signature)
tys, mems = parse_struct_signature(signature, type_alias)
Fiddle::CStructBuilder.create(CStruct, tys, mems)
end
typealias(alias_type, orig_type) Show source
将alias_type的类型别名设置为orig_type
# File ext/fiddle/lib/fiddle/import.rb, line 98
def typealias(alias_type, orig_type)
@type_alias[alias_type] = orig_type
end
union(signature) Show source
创建一个类来包装由signature描述的C联合。
MyUnion = union ['int i', 'char c']
# File ext/fiddle/lib/fiddle/import.rb, line 225
def union(signature)
tys, mems = parse_struct_signature(signature, type_alias)
Fiddle::CStructBuilder.create(CUnion, tys, mems)
end
value(ty, val=nil)
别名为:create_value
私有实例方法
parse_bind_options(opts) Show source
# File ext/fiddle/lib/fiddle/import.rb, line 136
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