diff options
author | ttate <ttate@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2005-02-04 13:35:37 +0000 |
---|---|---|
committer | ttate <ttate@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2005-02-04 13:35:37 +0000 |
commit | bda37095ca990568069aaf07dc6b3fa8ceebc327 (patch) | |
tree | 15043d94698579d6ab19544542479a42385cd1b5 /ext/dl/lib | |
parent | 4ae9132605dc7b0297bcda408ca7a2ad7de39d2f (diff) | |
download | ruby-bda37095ca990568069aaf07dc6b3fa8ceebc327.tar.gz |
added new files.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@7883 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext/dl/lib')
-rw-r--r-- | ext/dl/lib/dl/import.rb | 182 | ||||
-rw-r--r-- | ext/dl/lib/dl/struct.rb | 203 | ||||
-rw-r--r-- | ext/dl/lib/dl/types.rb | 40 |
3 files changed, 425 insertions, 0 deletions
diff --git a/ext/dl/lib/dl/import.rb b/ext/dl/lib/dl/import.rb new file mode 100644 index 0000000000..2f21e9195c --- /dev/null +++ b/ext/dl/lib/dl/import.rb @@ -0,0 +1,182 @@ +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 + nil + 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 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) + name, ctype, argtype = parse_signature(signature, @type_alias) + opt = parse_bind_options(opts) + f = import_function(name, ctype, argtype, opt[:call_type]) + @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) + CStructBuilder.create(CStruct, tys, mems) + end + + def union(signature) + tys, mems = parse_struct_signature(signature, @type_alias) + 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 diff --git a/ext/dl/lib/dl/struct.rb b/ext/dl/lib/dl/struct.rb new file mode 100644 index 0000000000..5c0775277e --- /dev/null +++ b/ext/dl/lib/dl/struct.rb @@ -0,0 +1,203 @@ +require 'dl' +require 'dl/pack.rb' + +module DL + class CStruct + def CStruct.entity_class() + CStructEntity + end + end + + class CUnion + def CUnion.entity_class() + CUnionEntity + end + end + + module CStructBuilder + def create(klass, types, members) + new_class = Class.new(klass){ + entity = nil + define_method(:initialize){|addr| + entity = klass.entity_class.new(addr, types) + entity.assign_names(members) + } + define_method(:to_ptr){ entity } + define_method(:to_i){ entity.to_i } + members.each{|name| + define_method(name){ entity[name] } + define_method(name + "="){|val| entity[name] = val } + } + } + size = klass.entity_class.size(types) + new_class.module_eval(<<-EOS) + def new_class.size() + #{size} + end + def new_class.malloc() + addr = DL.malloc(#{size}) + new(addr) + end + EOS + return new_class + end + module_function :create + end + + class CStructEntity < CPtr + include PackInfo + include ValueUtil + + def CStructEntity.malloc(types, func = nil) + addr = DL.malloc(CStructEntity.size(types)) + CStructEntity.new(addr, types, func) + end + + def CStructEntity.size(types) + offset = 0 + types.each_with_index{|t,i| + orig_offset = offset + if( t.is_a?(Array) ) + offset = PackInfo.align(orig_offset, PackInfo::ALIGN_MAP[TYPE_VOIDP]) + size = offset - orig_offset + offset += (PackInfo::SIZE_MAP[t[0]] * t[1]) + else + offset = PackInfo.align(orig_offset, PackInfo::ALIGN_MAP[t]) + size = offset - orig_offset + offset += PackInfo::SIZE_MAP[t] + end + } + offset = PackInfo.align(offset, PackInfo::ALIGN_MAP[TYPE_VOIDP]) + offset + end + + def initialize(addr, types, func = nil) + set_ctypes(types) + super(addr, @size, func) + end + + def assign_names(members) + @members = members + end + + def set_ctypes(types) + @ctypes = types + @offset = [] + offset = 0 + types.each_with_index{|t,i| + orig_offset = offset + if( t.is_a?(Array) ) + offset = align(orig_offset, ALIGN_MAP[TYPE_VOIDP]) + else + offset = align(orig_offset, ALIGN_MAP[t]) + end + size = offset - orig_offset + @offset[i] = offset + if( t.is_a?(Array) ) + offset += (SIZE_MAP[t[0]] * t[1]) + else + offset += SIZE_MAP[t] + end + } + offset = align(offset, ALIGN_MAP[TYPE_VOIDP]) + @size = offset + end + + def [](name) + idx = @members.index(name) + if( idx.nil? ) + raise(ArgumentError, "no such member: #{name}") + end + ty = @ctypes[idx] + if( ty.is_a?(Array) ) + r = super(@offset[idx], SIZE_MAP[ty[0]] * ty[1]) + else + r = super(@offset[idx], SIZE_MAP[ty.abs]) + end + packer = Packer.new([ty]) + val = packer.unpack([r]) + case ty + when Array + case ty[0] + when TYPE_VOIDP + val = val.collect{|v| CPtr.new(v)} + end + when TYPE_VOIDP + val = CPtr.new(val[0]) + else + val = val[0] + end + if( ty.is_a?(Integer) && (ty < 0) ) + return unsigned_value(val, ty) + elsif( ty.is_a?(Array) && (ty[0] < 0) ) + return val.collect{|v| unsigned_value(v,ty[0])} + else + return val + end + end + + def []=(name, val) + idx = @members.index(name) + if( idx.nil? ) + raise(ArgumentError, "no such member: #{name}") + end + ty = @ctypes[idx] + packer = Packer.new([ty]) + val = wrap_arg(val, ty, []) + buff = packer.pack([val].flatten()) + super(@offset[idx], buff.size, buff) + if( ty.is_a?(Integer) && (ty < 0) ) + return unsigned_value(val, ty) + elsif( ty.is_a?(Array) && (ty[0] < 0) ) + return val.collect{|v| unsigned_value(v,ty[0])} + else + return val + end + end + + def to_s() + super(@size) + end + end + + class CUnionEntity < CStruct + include PackInfo + + def CUnionEntity.malloc(types) + addr = DL.malloc(CUnionEntity.size(types)) + CUnionEntity.new(addr, types, func) + end + + def CUnionEntity.size(types) + size = 0 + types.each_with_index{|t,i| + if( t.is_a?(Array) ) + tsize = PackInfo::SIZE_MAP[t[0]] * t[1] + else + tsize = PackInfo::SIZE_MAP[t] + end + if( tsize > size ) + size = tsize + end + } + end + + def set_ctypes(types) + @ctypes = types + @offset = [] + @size = 0 + types.each_with_index{|t,i| + @offset[i] = 0 + if( t.is_a?(Array) ) + size = SIZE_MAP[t[0]] * t[1] + else + size = SIZE_MAP[t] + end + if( size > @size ) + @size = size + end + } + end + end +end + diff --git a/ext/dl/lib/dl/types.rb b/ext/dl/lib/dl/types.rb new file mode 100644 index 0000000000..b85ac890cd --- /dev/null +++ b/ext/dl/lib/dl/types.rb @@ -0,0 +1,40 @@ +module DL + module Win32Types + def included(m) + m.module_eval{ + typealias "DWORD", "unsigned long" + typealias "PDWORD", "unsigned long *" + typealias "WORD", "unsigned short" + typealias "PWORD", "unsigned short *" + typealias "BOOL", "int" + typealias "ATOM", "int" + typealias "BYTE", "unsigned char" + typealias "PBYTE", "unsigned char *" + typealias "UINT", "unsigned int" + typealias "ULONG", "unsigned long" + typealias "UCHAR", "unsigned char" + typealias "HANDLE", "unsigned long" + typealias "PHANDLE", "void*" + typealias "PVOID", "void*" + typealias "LPCSTR", "char*" + typealias "LPSTR", "char*" + typealias "HINSTANCE", "unsigned int" + typealias "HDC", "unsigned int" + typealias "HWND", "unsigned int" + } + end + module_function :included + end + + module BasicTypes + def included(m) + m.module_eval{ + typealias "uint", "unsigned int" + typealias "u_int", "unsigned int" + typealias "ulong", "unsigned long" + typealias "u_long", "unsigned long" + } + end + module_function :included + end +end |