module DL::Importer
DL::Importer includes the means to dynamically load libraries and build modules around them including calling extern functions within the C library that has been loaded.
Example¶ ↑
require 'dl' require 'dl/import' module LibSum extend DL::Importer dlload './libsum.so' extern 'double sum(double*, int)' extern 'double split(double)' end
Public Instance Methods
[](name)
click to toggle source
# File ext/dl/lib/dl/import.rb, line 203 def [](name) @func_map[name] end
bind(signature, *opts, &blk)
click to toggle source
# File ext/dl/lib/dl/import.rb, line 154 def bind(signature, *opts, &blk) @type_alias ||= nil 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) when :temp, :temporal f = create_temp_function(name, ctype, argtype, h[:call_type]) when :carried f = create_carried_function(name, ctype, argtype, h[:call_type], h[:carrier]) 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)
click to toggle source
# File ext/dl/lib/dl/import.rb, line 244 def bind_function(name, ctype, argtype, call_type = nil, &block) if DL.fiddle? klass = Function.instance_eval { class_fiddle_closure_cfunc } abi = Function.instance_eval { call_type_to_abi(call_type) } closure = Class.new(klass) { define_method(:call, block) }.new(ctype, argtype, abi, name) Function.new(closure, argtype, abi) else f = Function.new(CFunc.new(0, ctype, name, call_type || :cdecl), argtype) f.bind(&block) f end end
create_carried_function(name, ctype, argtype, call_type = nil, n = 0)
click to toggle source
# File ext/dl/lib/dl/import.rb, line 264 def create_carried_function(name, ctype, argtype, call_type = nil, n = 0) CarriedFunction.new(CFunc.new(0, ctype, name, call_type || :cdecl), argtype, n) end
create_temp_function(name, ctype, argtype, call_type = nil)
click to toggle source
# File ext/dl/lib/dl/import.rb, line 260 def create_temp_function(name, ctype, argtype, call_type = nil) TempFunction.new(CFunc.new(0, ctype, name, call_type || :cdecl), argtype) end
create_value(ty, val=nil)
click to toggle source
# File ext/dl/lib/dl/import.rb, line 207 def create_value(ty, val=nil) s = struct([ty + " value"]) ptr = s.malloc() if( val ) ptr.value = val end return ptr end
Also aliased as: value
dlload(*libs)
click to toggle source
# File ext/dl/lib/dl/import.rb, line 55 def dlload(*libs) handles = libs.collect{|lib| case lib when nil nil when Handle lib when Importer lib.handlers else begin DL.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)
click to toggle source
# File ext/dl/lib/dl/import.rb, line 131 def extern(signature, *opts) @type_alias ||= nil 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()
click to toggle source
# File ext/dl/lib/dl/import.rb, line 223 def handler defined?(@handler) or raise "call dlload before importing symbols and functions" @handler end
import_function(name, ctype, argtype, call_type = nil)
click to toggle source
# File ext/dl/lib/dl/import.rb, line 236 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(CFunc.new(addr, ctype, name, call_type || :cdecl), argtype) end
import_symbol(name)
click to toggle source
# File ext/dl/lib/dl/import.rb, line 228 def import_symbol(name) addr = handler.sym(name) if( !addr ) raise(DLError, "cannot find the symbol: #{name}") end CPtr.new(addr) end
import_value(ty, addr)
click to toggle source
# File ext/dl/lib/dl/import.rb, line 217 def import_value(ty, addr) s = struct([ty + " value"]) ptr = s.new(addr) return ptr end
sizeof(ty)
click to toggle source
# File ext/dl/lib/dl/import.rb, line 81 def sizeof(ty) @type_alias ||= nil 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_LON 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 CPtr[ty].size() end
struct(signature)
click to toggle source
Creates a class to wrap the C struct described by signature
.
MyStruct = struct ['int i', 'char c']
# File ext/dl/lib/dl/import.rb, line 188 def struct(signature) @type_alias ||= nil tys, mems = parse_struct_signature(signature, @type_alias) DL::CStructBuilder.create(CStruct, tys, mems) end
typealias(alias_type, orig_type)
click to toggle source
# File ext/dl/lib/dl/import.rb, line 77 def typealias(alias_type, orig_type) @type_alias[alias_type] = orig_type end
union(signature)
click to toggle source
Creates a class to wrap the C union described by signature
.
MyUnion = union ['int i', 'char c']
# File ext/dl/lib/dl/import.rb, line 197 def union(signature) @type_alias ||= nil tys, mems = parse_struct_signature(signature, @type_alias) DL::CStructBuilder.create(CUnion, tys, mems) end
Private Instance Methods
parse_bind_options(opts)
click to toggle source
# File ext/dl/lib/dl/import.rb, line 114 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