From 0dc342de848a642ecce8db697b8fecd83a63e117 Mon Sep 17 00:00:00 2001 From: yugui Date: Mon, 25 Aug 2008 15:02:05 +0000 Subject: added tag v1_9_0_4 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/tags/v1_9_0_4@18845 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- trunk/ext/dl/lib/dl/import.rb | 215 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 215 insertions(+) create mode 100644 trunk/ext/dl/lib/dl/import.rb (limited to 'trunk/ext/dl/lib/dl/import.rb') diff --git a/trunk/ext/dl/lib/dl/import.rb b/trunk/ext/dl/lib/dl/import.rb new file mode 100644 index 0000000000..f6fb35944d --- /dev/null +++ b/trunk/ext/dl/lib/dl/import.rb @@ -0,0 +1,215 @@ +require 'dl' +require 'dl/func.rb' +require 'dl/struct.rb' +require 'dl/cparser.rb' + +module DL + class CompositeHandler + def initialize(handlers) + @handlers = handlers + end + + def handlers() + @handlers + end + + def sym(symbol) + @handlers.each{|handle| + if( handle ) + begin + addr = handle.sym(symbol) + return addr + rescue DLError + end + end + } + return nil + end + + def [](symbol) + sym(symbol) + end + end + + module Importer + include DL + include CParser + extend Importer + + 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 + + def typealias(alias_type, orig_type) + @type_alias[alias_type] = orig_type + end + + 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_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 + + def parse_bind_options(opts) + h = {} + prekey = nil + 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 + private :parse_bind_options + + 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)} + module_eval(<<-EOS) + def #{name}(*args, &block) + @func_map['#{name}'].call(*args,&block) + end + EOS + module_function(name) + f + end + + 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) + 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)} + module_eval(<<-EOS) + def #{name}(*args,&block) + @func_map['#{name}'].call(*args,&block) + end + EOS + module_function(name) + f + end + + def struct(signature) + tys, mems = parse_struct_signature(signature, @type_alias) + DL::CStructBuilder.create(CStruct, tys, mems) + end + + def union(signature) + tys, mems = parse_struct_signature(signature, @type_alias) + DL::CStructBuilder.create(CUnion, tys, mems) + end + + def [](name) + @func_map[name] + end + + def create_value(ty, val=nil) + s = struct([ty + " value"]) + ptr = s.malloc() + if( val ) + ptr.value = val + end + return ptr + end + alias value create_value + + def import_value(ty, addr) + s = struct([ty + " value"]) + ptr = s.new(addr) + return ptr + end + + def import_symbol(name) + addr = @handler.sym(name) + if( !addr ) + raise(DLError, "cannot find the symbol: #{name}") + end + CPtr.new(addr) + end + + 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 + + def bind_function(name, ctype, argtype, call_type = nil, &block) + f = Function.new(CFunc.new(0, ctype, name, call_type || :cdecl), argtype) + f.bind(&block) + f + end + + def create_temp_function(name, ctype, argtype, call_type = nil) + TempFunction.new(CFunc.new(0, ctype, name, call_type || :cdecl), argtype) + end + + 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 + end +end -- cgit v1.2.3