From 8d08d9f5134a07af00f9e2ef8a4938e40503f873 Mon Sep 17 00:00:00 2001 From: ttate Date: Fri, 5 Apr 2002 05:11:11 +0000 Subject: Add dl/struct.rb. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2339 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/dl/lib/dl/import.rb | 85 +++++------------ ext/dl/lib/dl/struct.rb | 107 ++++++++++++++++++++++ ext/dl/lib/dl/types.rb | 237 +++++++++++++++++++++++++++++++----------------- 3 files changed, 288 insertions(+), 141 deletions(-) create mode 100644 ext/dl/lib/dl/struct.rb (limited to 'ext/dl') diff --git a/ext/dl/lib/dl/import.rb b/ext/dl/lib/dl/import.rb index 3530953e0c..a9d1806a04 100644 --- a/ext/dl/lib/dl/import.rb +++ b/ext/dl/lib/dl/import.rb @@ -8,6 +8,18 @@ module DL LIB_MAP = {} module Internal + def init_types() + if( !@types ) + @types = ::DL::Types.new + end + end + + def init_sym() + if( !@SYM ) + @SYM = {} + end + end + def dlload(*libnames) if( !defined?(@LIBS) ) @LIBS = [] @@ -40,15 +52,22 @@ module DL end end + # example: + # typealias("uint", "unsigned int") + # + def typealias(*args) + init_types() + @types.typealias(*args) + end + # example: # import("get_length", "int", ["void*", "int"]) # def import(name, rettype, argtypes = nil) - if( !defined?(@SYM) ) - @SYM = {} - end + init_types() + init_sym() @LIBS.each{|lib| - rty,_,rdec = encode_type(rettype) + rty,_,rdec = @types.encode_type(rettype) ty,enc,dec = encode_types(argtypes) symty = rty + ty @@ -100,58 +119,14 @@ module DL def _retval_ return @retval end - - def typealias(ty1, ty2, enc=nil, dec=nil) - check_type - @TYDEFS.unshift([ty1,ty2, enc,dec]) - end - - def encode_type(ty) - check_type - orig_ty = ty - enc = nil - dec = nil - @TYDEFS.each{|t1,t2,c1,c2| - if( t1.is_a?(String) ) - t1 = Regexp.new("^" + t1 + "$") - end - if( ty =~ t1 ) - ty = ty.gsub(t1,t2) - if( enc ) - if( c1 ) - conv1 = enc - enc = proc{|v| c1.call(conv1.call(v))} - end - else - if( c1 ) - enc = c1 - end - end - if( dec ) - if( c2 ) - conv2 = dec - dec = proc{|v| c2.call(conv2.call(v))} - end - else - if( c2 ) - dec = c2 - end - end - end - } - ty = ty.strip - if( ty.length != 1 ) - raise(TypeError, "unknown type: #{orig_ty}.") - end - return [ty,enc,dec] - end def encode_types(tys) + init_types() encty = [] enc = nil dec = nil tys.each_with_index{|ty,idx| - ty,c1,c2 = encode_type(ty) + ty,c1,c2,_,_ = @types.encode_type(ty) encty.push(ty) if( enc ) if( c1 ) @@ -176,16 +151,6 @@ module DL } return [encty.join, enc, dec] end - - def check_type - if( !defined?(@TYDEFS) ) - init_type - end - end - - def init_type - @TYDEFS = TYPES.collect{|ty| ty[0..3]} - end end # end of Internal include Internal end # end of Importable diff --git a/ext/dl/lib/dl/struct.rb b/ext/dl/lib/dl/struct.rb new file mode 100644 index 0000000000..b16aa6e6b0 --- /dev/null +++ b/ext/dl/lib/dl/struct.rb @@ -0,0 +1,107 @@ +# -*- ruby -*- + +require 'dl' +require 'dl/import' + +module DL + module Importable + module Internal + def define_struct(contents) + init_types() + Struct.new(@types, contents) + end + + def define_union(contents) + init_types() + Union.new(@types, contents) + end + + class Memory + def initialize(ptr, names, ty, len, enc, dec) + @ptr = ptr + @names = names + @ty = ty + @len = len + @enc = enc + @dec = dec + + # define methods + @names.each{|name| + instance_eval [ + "def #{name}", + " v = @ptr[\"#{name}\"]", + " v = @dec[\"#{name}\"].call(v,#{@len}) if @dec[\"#{name}\"]", + " return v", + "end", + ].join("\n") + } + end + end + + class Struct + def initialize(types, contents) + @names = [] + @ty = {} + @len = {} + @enc = {} + @dec = {} + @size = 0 + @tys = "" + @types = types + parse(contents) + end + + def new + ptr = DL::malloc(@size) + ptr.struct!(@tys, *@names) + mem = Memory.new(ptr, @names, @ty, @len, @enc, @dec) + return mem + end + + def parse(contents) + contents.each{|elem| + name,ty,num,enc,dec = parse_elem(elem) + @names.push(name) + @ty[name] = ty + @len[name] = num + @enc[name] = enc + @dec[name] = dec + if( num ) + @tys += "#{ty}#{num}" + else + @tys += ty + end + } + @size = DL.sizeof(@tys) + end + + def parse_elem(elem) + elem.strip! + case elem + when /^([\w\d_\*]+)([\*\s]+)([\w\d_]+)$/ + ty = ($1 + $2).strip + name = $3 + num = nil; + when /^([\w\d_\*]+)([\*\s]+)([\w\d_]+)\[(\d+)\]$/ + ty = ($1 + $2).strip + name = $3 + num = $4.to_i + else + raise(RuntimeError, "invalid element: #{elem}") + end + ty,_,_,enc,dec = @types.encode_type(ty) + return [name,ty,num,enc,dec] + end + end # class Struct + + class Union < Struct + def new + ptr = DL::malloc(@size) + ptr.union!(@tys, *@names) + mem = Memory.new(ptr, @names, @ty, @len, @enc, @dec) + return mem + end + end + end # module Internal + end # module Importable +end # module DL diff --git a/ext/dl/lib/dl/types.rb b/ext/dl/lib/dl/types.rb index c040f2cecc..9b44d02b91 100644 --- a/ext/dl/lib/dl/types.rb +++ b/ext/dl/lib/dl/types.rb @@ -3,86 +3,161 @@ require 'dl' module DL - TYPES = [ - # FORMAT: - # ["alias name", "type name", - # encoding_method, decoding_method, for function prototypes - # encoding_method, decoding_method] for structures (not implemented) + class Types + TYPES = [ + # FORMAT: + # ["alias name", "type name", + # encoding_method, decoding_method, for function prototypes + # encoding_method, decoding_method] for structures (not implemented) + + # for Windows + ["DWORD", "unsigned long", nil, nil, nil, nil], + ["PDWORD", "unsigned long *", nil, nil, nil, nil], + ["WORD", "unsigned int", nil, nil, nil, nil], + ["PWORD", "unsigned int *", nil, nil, nil, nil], + ["BOOL", "ibool", nil, nil, nil, nil], + ["ATOM", "int", nil, nil, nil, nil], + ["BYTE", "unsigned char", nil, nil, nil, nil], + ["PBYTE", "unsigned char *", nil, nil, nil, nil], + ["UINT", "unsigned int", nil, nil, nil, nil], + ["ULONG", "unsigned long", nil, nil, nil, nil], + ["UCHAR", "unsigned char", nil, nil, nil, nil], + ["HANDLE", "unsigned long", nil, nil, nil, nil], + ["PHANDLE","void*", nil, nil, nil, nil], + ["PVOID", "void*", nil, nil, nil, nil], + ["LPCSTR", "char*", nil, nil, nil, nil], + + # Others + ["uint", "unsigned int", nil, nil, nil, nil], + ["u_int", "unsigned int", nil, nil, nil, nil], + ["ulong", "unsigned long", nil, nil, nil, nil], + ["u_long", "unsigned long", nil, nil, nil, nil], + + # DL::Importable primitive types + ["ibool", "I", + proc{|v| v ? 1 : 0}, + proc{|v| (v != 0) ? true : false}, + nil, nil], + ["cbool", "C", + proc{|v| v ? 1 : 0}, + proc{|v| (v != 0) ? true : false}, + nil, nil], + ["lbool", "L", + proc{|v| v ? 1 : 0}, + proc{|v| (v != 0) ? true : false}, + nil, nil], + ["unsigned char", "I", + proc{|v| [v].pack("C").unpack("c")[0]}, + proc{|v| [v].pack("c").unpack("C")[0]}, + nil, nil], + ["unsigned int", "I", + proc{|v| [v].pack("I").unpack("i")[0]}, + proc{|v| [v].pack("i").unpack("I")[0]}, + nil, nil], + ["unsigned long", "L", + proc{|v| [v].pack("L").unpack("l")[0]}, + proc{|v| [v].pack("l").unpack("L")[0]}, + nil, nil], + ["unsigned char ref", "i", + proc{|v| [v].pack("C").unpack("c")[0]}, + proc{|v| [v].pack("c").unpack("C")[0]}, + nil, nil], + ["unsigned int ref", "i", + proc{|v| [v].pack("I").unpack("i")[0]}, + proc{|v| [v].pack("i").unpack("I")[0]}, + nil, nil], + ["unsigned long ref", "l", + proc{|v| [v].pack("L").unpack("l")[0]}, + proc{|v| [v].pack("l").unpack("L")[0]}, + nil, nil], + ["char ref", "c", nil, nil, nil, nil], + ["short ref", "h", nil, nil, nil, nil], + ["int ref", "i", nil, nil, nil, nil], + ["long ref", "l", nil, nil, nil, nil], + ["float ref", "f", nil, nil, nil, nil], + ["double ref","d", nil, nil, nil, nil], + ["char", "C", nil, nil, nil, nil], + ["short", "H", nil, nil, nil, nil], + ["int", "I", nil, nil, nil, nil], + ["long", "L", nil, nil, nil, nil], + ["float", "F", nil, nil, nil, nil], + ["double", "D", nil, nil, nil, nil], + [/.+\*/, "P", nil, nil, nil, nil], + [/.+\[\]/, "a", nil, nil, nil, nil], + ["void", "0", nil, nil, nil, nil], + ] - # for Windows - ["DWORD", "unsigned long", nil, nil, nil, nil], - ["PDWORD", "unsigned long *", nil, nil, nil, nil], - ["WORD", "unsigned int", nil, nil, nil, nil], - ["PWORD", "unsigned int *", nil, nil, nil, nil], - ["BOOL", "ibool", nil, nil, nil, nil], - ["ATOM", "int", nil, nil, nil, nil], - ["BYTE", "unsigned char", nil, nil, nil, nil], - ["PBYTE", "unsigned char *", nil, nil, nil, nil], - ["UINT", "unsigned int", nil, nil, nil, nil], - ["ULONG", "unsigned long", nil, nil, nil, nil], - ["UCHAR", "unsigned char", nil, nil, nil, nil], - ["HANDLE", "unsigned long", nil, nil, nil, nil], - ["PHANDLE","void*", nil, nil, nil, nil], - ["PVOID", "void*", nil, nil, nil, nil], - ["LPCSTR", "char*", nil, nil, nil, nil], - - # Others - ["uint", "unsigned int", nil, nil, nil, nil], - ["u_int", "unsigned int", nil, nil, nil, nil], - ["ulong", "unsigned long", nil, nil, nil, nil], - ["u_long", "unsigned long", nil, nil, nil, nil], - - # DL::Importable primitive types - ["ibool", "I", - proc{|v| v ? 1 : 0}, - proc{|v| (v != 0) ? true : false}, - nil, nil], - ["cbool", "C", - proc{|v| v ? 1 : 0}, - proc{|v| (v != 0) ? true : false}, - nil, nil], - ["lbool", "L", - proc{|v| v ? 1 : 0}, - proc{|v| (v != 0) ? true : false}, - nil, nil], - ["unsigned char", "I", - proc{|v| [v].pack("C").unpack("c")[0]}, - proc{|v| [v].pack("c").unpack("C")[0]}, - nil, nil], - ["unsigned int", "I", - proc{|v| [v].pack("I").unpack("i")[0]}, - proc{|v| [v].pack("i").unpack("I")[0]}, - nil, nil], - ["unsigned long", "L", - proc{|v| [v].pack("L").unpack("l")[0]}, - proc{|v| [v].pack("l").unpack("L")[0]}, - nil, nil], - ["unsigned char ref", "i", - proc{|v| [v].pack("C").unpack("c")[0]}, - proc{|v| [v].pack("c").unpack("C")[0]}, - nil, nil], - ["unsigned int ref", "i", - proc{|v| [v].pack("I").unpack("i")[0]}, - proc{|v| [v].pack("i").unpack("I")[0]}, - nil, nil], - ["unsigned long ref", "l", - proc{|v| [v].pack("L").unpack("l")[0]}, - proc{|v| [v].pack("l").unpack("L")[0]}, - nil, nil], - ["char ref", "c", nil, nil, nil, nil], - ["short ref", "h", nil, nil, nil, nil], - ["int ref", "i", nil, nil, nil, nil], - ["long ref", "l", nil, nil, nil, nil], - ["float ref", "f", nil, nil, nil, nil], - ["double ref","d", nil, nil, nil, nil], - ["char", "C", nil, nil, nil, nil], - ["short", "H", nil, nil, nil, nil], - ["int", "I", nil, nil, nil, nil], - ["long", "L", nil, nil, nil, nil], - ["float", "F", nil, nil, nil, nil], - ["double", "D", nil, nil, nil, nil], - [/.+\*/, "P", nil, nil, nil, nil], - [/.+\[\]/, "a", nil, nil, nil, nil], - ["void", "0", nil, nil, nil, nil], - ] + def initialize + init_types() + end + + def typealias(ty1, ty2, enc=nil, dec=nil, senc=nil, sdec=nil) + @TYDEFS.unshift([ty1,ty2, enc,dec, senc, sdec]) + end + + def init_types + @TYDEFS = TYPES.dup + end + + def encode_type(ty) + orig_ty = ty + enc = nil + dec = nil + senc = nil + sdec = nil + @TYDEFS.each{|t1,t2,c1,c2,c3,c4| + if( t1.is_a?(String) ) + t1 = Regexp.new("^" + t1 + "$") + end + if( ty =~ t1 ) + ty = ty.gsub(t1,t2) + if( enc ) + if( c1 ) + conv1 = enc + enc = proc{|v| c1.call(conv1.call(v))} + end + else + if( c1 ) + enc = c1 + end + end + if( dec ) + if( c2 ) + conv2 = dec + dec = proc{|v| c2.call(conv2.call(v))} + end + else + if( c2 ) + dec = c2 + end + end + if( senc ) + if( c3 ) + conv3 = senc + senc = proc{|v| c3.call(conv3.call(v))} + end + else + if( c3 ) + senc = c3 + end + end + if( sdec ) + if( c4 ) + conv4 = sdec + sdec = proc{|v| c4.call(conv4.call(v))} + end + else + if( c4 ) + sdec = c4 + end + end + end + } + ty = ty.strip + if( ty.length != 1 ) + raise(TypeError, "unknown type: #{orig_ty}.") + end + return [ty,enc,dec,senc,sdec] + end + end # end of Types end -- cgit v1.2.3