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.
require 'dl' require 'dl/import' module LibSum extend DL::Importer dlload './libsum.so' extern 'double sum(double*, int)' extern 'double split(double)' end
# File dl/lib/dl/import.rb, line 203 def [](name) @func_map[name] end
# File 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
# File 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
# File 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
# File 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
# File 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
# File 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
# File 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
# File dl/lib/dl/import.rb, line 223 def handler defined?(@handler) or raise "call dlload before importing symbols and functions" @handler end
# File 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
# File 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
# File dl/lib/dl/import.rb, line 217 def import_value(ty, addr) s = struct([ty + " value"]) ptr = s.new(addr) return ptr end
# File 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
Creates a class to wrap the C struct described by signature
.
MyStruct = struct ['int i', 'char c']
# File 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
# File dl/lib/dl/import.rb, line 77 def typealias(alias_type, orig_type) @type_alias[alias_type] = orig_type end
Creates a class to wrap the C union described by signature
.
MyUnion = union ['int i', 'char c']
# File 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
Commenting is here to help enhance the documentation. For example, code samples, or clarification of the documentation.
If you have questions about Ruby or the documentation, please post to one of the Ruby mailing lists. You will get better, faster, help that way.
If you wish to post a correction of the docs, please do so, but also file bug report so that it can be corrected for the next release. Thank you.
If you want to help improve the Ruby documentation, please visit Documenting-ruby.org.