summaryrefslogtreecommitdiff
path: root/ruby_1_8_6/ext/dl/lib
diff options
context:
space:
mode:
Diffstat (limited to 'ruby_1_8_6/ext/dl/lib')
-rw-r--r--ruby_1_8_6/ext/dl/lib/dl/import.rb225
-rw-r--r--ruby_1_8_6/ext/dl/lib/dl/struct.rb149
-rw-r--r--ruby_1_8_6/ext/dl/lib/dl/types.rb245
-rw-r--r--ruby_1_8_6/ext/dl/lib/dl/win32.rb25
4 files changed, 644 insertions, 0 deletions
diff --git a/ruby_1_8_6/ext/dl/lib/dl/import.rb b/ruby_1_8_6/ext/dl/lib/dl/import.rb
new file mode 100644
index 0000000000..01ee2490e8
--- /dev/null
+++ b/ruby_1_8_6/ext/dl/lib/dl/import.rb
@@ -0,0 +1,225 @@
+# -*- ruby -*-
+
+require 'dl'
+require 'dl/types'
+
+module DL
+ module Importable
+ LIB_MAP = {}
+
+ module Internal
+ def init_types()
+ @types ||= ::DL::Types.new
+ end
+
+ def init_sym()
+ @SYM ||= {}
+ end
+
+ def [](name)
+ return @SYM[name.to_s][0]
+ end
+
+ def dlload(*libnames)
+ if( !defined?(@LIBS) )
+ @LIBS = []
+ end
+ libnames.each{|libname|
+ if( !LIB_MAP[libname] )
+ LIB_MAP[libname] = DL.dlopen(libname)
+ end
+ @LIBS.push(LIB_MAP[libname])
+ }
+ end
+ alias dllink :dlload
+
+ def parse_cproto(proto)
+ proto = proto.gsub(/\s+/, " ").strip
+ case proto
+ when /^([\d\w\*_\s]+)\(([\d\w\*_\s\,\[\]]*)\)$/
+ ret = $1
+ args = $2.strip()
+ ret = ret.split(/\s+/)
+ args = args.split(/\s*,\s*/)
+ func = ret.pop()
+ if( func =~ /^\*/ )
+ func.gsub!(/^\*+/,"")
+ ret.push("*")
+ end
+ ret = ret.join(" ")
+ return [func, ret, args]
+ else
+ raise(RuntimeError,"can't parse the function prototype: #{proto}")
+ end
+ end
+
+ # example:
+ # extern "int strlen(char*)"
+ #
+ def extern(proto)
+ func,ret,args = parse_cproto(proto)
+ return import(func, ret, args)
+ end
+
+ # example:
+ # callback "int method_name(int, char*)"
+ #
+ def callback(proto)
+ func,ret,args = parse_cproto(proto)
+
+ init_types()
+ init_sym()
+
+ rty,renc,rdec = @types.encode_return_type(ret)
+ if( !rty )
+ raise(TypeError, "unsupported type: #{ret}")
+ end
+ ty,enc,dec = encode_argument_types(args)
+ symty = rty + ty
+
+ module_eval("module_function :#{func}")
+ sym = module_eval([
+ "DL::callback(\"#{symty}\"){|*args|",
+ " sym,rdec,enc,dec = @SYM['#{func}']",
+ " args = enc.call(args) if enc",
+ " r,rs = #{func}(*args)",
+ " r = renc.call(r) if rdec",
+ " rs = dec.call(rs) if (dec && rs)",
+ " @retval = r",
+ " @args = rs",
+ " r",
+ "}",
+ ].join("\n"))
+
+ @SYM[func] = [sym,rdec,enc,dec]
+
+ return sym
+ end
+
+ # example:
+ # typealias("uint", "unsigned int")
+ #
+ def typealias(alias_type, ty1, enc1=nil, dec1=nil, ty2=nil, enc2=nil, dec2=nil)
+ init_types()
+ @types.typealias(alias_type, ty1, enc1, dec1,
+ ty2||ty1, enc2, dec2)
+ end
+
+ # example:
+ # symbol "foo_value"
+ # symbol "foo_func", "IIP"
+ #
+ def symbol(name, ty = nil)
+ sym = nil
+ @LIBS.each{|lib|
+ begin
+ if( ty )
+ sym = lib[name, ty]
+ else
+ sym = lib[name]
+ end
+ rescue
+ next
+ end
+ }
+ if( !sym )
+ raise(RuntimeError, "can't find the symbol `#{name}'")
+ end
+ return sym
+ end
+
+ # example:
+ # import("get_length", "int", ["void*", "int"])
+ #
+ def import(name, rettype, argtypes = nil)
+ init_types()
+ init_sym()
+
+ rty,_,rdec = @types.encode_return_type(rettype)
+ if( !rty )
+ raise(TypeError, "unsupported type: #{rettype}")
+ end
+ ty,enc,dec = encode_argument_types(argtypes)
+ symty = rty + ty
+
+ sym = symbol(name, symty)
+
+ mname = name.dup
+ if( ?A <= mname[0] && mname[0] <= ?Z )
+ mname[0,1] = mname[0,1].downcase
+ end
+ @SYM[mname] = [sym,rdec,enc,dec]
+
+ module_eval [
+ "def #{mname}(*args)",
+ " sym,rdec,enc,dec = @SYM['#{mname}']",
+ " args = enc.call(args) if enc",
+ if( $DEBUG )
+ " p \"[DL] call #{mname} with \#{args.inspect}\""
+ else
+ ""
+ end,
+ " r,rs = sym.call(*args)",
+ if( $DEBUG )
+ " p \"[DL] retval=\#{r.inspect} args=\#{rs.inspect}\""
+ else
+ ""
+ end,
+ " r = rdec.call(r) if rdec",
+ " rs = dec.call(rs) if dec",
+ " @retval = r",
+ " @args = rs",
+ " return r",
+ "end",
+ "module_function :#{mname}",
+ ].join("\n")
+
+ return sym
+ end
+
+ def _args_
+ return @args
+ end
+
+ def _retval_
+ return @retval
+ end
+
+ def encode_argument_types(tys)
+ init_types()
+ encty = []
+ enc = nil
+ dec = nil
+ tys.each_with_index{|ty,idx|
+ ty,c1,c2 = @types.encode_argument_type(ty)
+ if( !ty )
+ raise(TypeError, "unsupported type: #{ty}")
+ end
+ encty.push(ty)
+ if( enc )
+ if( c1 )
+ conv1 = enc
+ enc = proc{|v| v = conv1.call(v); v[idx] = c1.call(v[idx]); v}
+ end
+ else
+ if( c1 )
+ enc = proc{|v| v[idx] = c1.call(v[idx]); v}
+ end
+ end
+ if( dec )
+ if( c2 )
+ conv2 = dec
+ dec = proc{|v| v = conv2.call(v); v[idx] = c2.call(v[idx]); v}
+ end
+ else
+ if( c2 )
+ dec = proc{|v| v[idx] = c2.call(v[idx]); v}
+ end
+ end
+ }
+ return [encty.join, enc, dec]
+ end
+ end # end of Internal
+ include Internal
+ end # end of Importable
+end
diff --git a/ruby_1_8_6/ext/dl/lib/dl/struct.rb b/ruby_1_8_6/ext/dl/lib/dl/struct.rb
new file mode 100644
index 0000000000..33f303fe22
--- /dev/null
+++ b/ruby_1_8_6/ext/dl/lib/dl/struct.rb
@@ -0,0 +1,149 @@
+# -*- ruby -*-
+
+require 'dl'
+require 'dl/import'
+
+module DL
+ module Importable
+ module Internal
+ def define_struct(contents)
+ init_types()
+ Struct.new(@types, contents)
+ end
+ alias struct define_struct
+
+ def define_union(contents)
+ init_types()
+ Union.new(@types, contents)
+ end
+ alias union define_union
+
+ 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}\"]",
+ " if( @len[\"#{name}\"] )",
+ " v = v.collect{|x| @dec[\"#{name}\"] ? @dec[\"#{name}\"].call(x) : x }",
+ " else",
+ " v = @dec[\"#{name}\"].call(v) if @dec[\"#{name}\"]",
+ " end",
+ " return v",
+ "end",
+ "def #{name}=(v)",
+ " if( @len[\"#{name}\"] )",
+ " v = v.collect{|x| @enc[\"#{name}\"] ? @enc[\"#{name}\"].call(x) : x }",
+ " else",
+ " v = @enc[\"#{name}\"].call(v) if @enc[\"#{name}\"]",
+ " end",
+ " @ptr[\"#{name}\"] = v",
+ " return v",
+ "end",
+ ].join("\n")
+ }
+ end
+
+ def to_ptr
+ return @ptr
+ end
+
+ def size
+ return @ptr.size
+ end
+ end
+
+ class Struct
+ def initialize(types, contents)
+ @names = []
+ @ty = {}
+ @len = {}
+ @enc = {}
+ @dec = {}
+ @size = 0
+ @tys = ""
+ @types = types
+ parse(contents)
+ end
+
+ def size
+ return @size
+ end
+
+ def members
+ return @names
+ end
+
+ # ptr must be a PtrData object.
+ def new(ptr)
+ ptr.struct!(@tys, *@names)
+ mem = Memory.new(ptr, @names, @ty, @len, @enc, @dec)
+ return mem
+ end
+
+ def malloc(size = nil)
+ if( !size )
+ size = @size
+ end
+ ptr = DL::malloc(size)
+ return new(ptr)
+ 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_struct_type(ty)
+ if( !ty )
+ raise(TypeError, "unsupported type: #{ty}")
+ end
+ 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/ruby_1_8_6/ext/dl/lib/dl/types.rb b/ruby_1_8_6/ext/dl/lib/dl/types.rb
new file mode 100644
index 0000000000..1144917dae
--- /dev/null
+++ b/ruby_1_8_6/ext/dl/lib/dl/types.rb
@@ -0,0 +1,245 @@
+# -*- ruby -*-
+
+require 'dl'
+
+module DL
+ class Types
+ TYPES = [
+ # FORMAT:
+ # ["alias name",
+ # "type name", encoding_method, decoding_method, for function prototypes
+ # "type name", encoding_method, decoding_method] for structures (not implemented)
+
+ # for Windows
+ ["DWORD", "unsigned long", nil, nil,
+ "unsigned long", nil, nil],
+ ["PDWORD", "unsigned long *", nil, nil,
+ "unsigned long *", nil, nil],
+ ["WORD", "unsigned short", nil, nil,
+ "unsigned short", nil, nil],
+ ["PWORD", "unsigned int *", nil, nil,
+ "unsigned int *", nil, nil],
+ ["BYTE", "unsigned char", nil, nil,
+ "unsigned char", nil, nil],
+ ["PBYTE", "unsigned char *", nil, nil,
+ "unsigned char *", nil, nil],
+ ["BOOL", "ibool", nil, nil,
+ "ibool", nil, nil],
+ ["ATOM", "int", nil, nil,
+ "int", nil, nil],
+ ["BYTE", "unsigned char", nil, nil,
+ "unsigned char", nil, nil],
+ ["PBYTE", "unsigned char *", nil, nil,
+ "unsigned char *", nil, nil],
+ ["UINT", "unsigned int", nil, nil,
+ "unsigned int", nil, nil],
+ ["ULONG", "unsigned long", nil, nil,
+ "unsigned long", nil, nil],
+ ["UCHAR", "unsigned char", nil, nil,
+ "unsigned char", nil, nil],
+ ["HANDLE", "unsigned long", nil, nil,
+ "unsigned long", nil, nil],
+ ["PHANDLE","void*", nil, nil,
+ "void*", nil, nil],
+ ["PVOID", "void*", nil, nil,
+ "void*", nil, nil],
+ ["LPCSTR", "char*", nil, nil,
+ "char*", nil, nil],
+ ["HDC", "unsigned int", nil, nil,
+ "unsigned int", nil, nil],
+ ["HWND", "unsigned int", nil, nil,
+ "unsigned int", nil, nil],
+
+ # Others
+ ["uint", "unsigned int", nil, nil,
+ "unsigned int", nil, nil],
+ ["u_int", "unsigned int", nil, nil,
+ "unsigned int", nil, nil],
+ ["ulong", "unsigned long", nil, nil,
+ "unsigned long", nil, nil],
+ ["u_long", "unsigned long", nil, nil,
+ "unsigned long", nil, nil],
+
+ # DL::Importable primitive types
+ ["ibool",
+ "I",
+ proc{|v| v ? 1 : 0},
+ proc{|v| (v != 0) ? true : false},
+ "I",
+ proc{|v| v ? 1 : 0 },
+ proc{|v| (v != 0) ? true : false} ],
+ ["cbool",
+ "C",
+ proc{|v| v ? 1 : 0},
+ proc{|v| (v != 0) ? true : false},
+ "C",
+ proc{|v,len| v ? 1 : 0},
+ proc{|v,len| (v != 0) ? true : false}],
+ ["lbool",
+ "L",
+ proc{|v| v ? 1 : 0},
+ proc{|v| (v != 0) ? true : false},
+ "L",
+ proc{|v,len| v ? 1 : 0},
+ proc{|v,len| (v != 0) ? true : false}],
+ ["unsigned char",
+ "C",
+ proc{|v| [v].pack("C").unpack("c")[0]},
+ proc{|v| [v].pack("c").unpack("C")[0]},
+ "C",
+ proc{|v| [v].pack("C").unpack("c")[0]},
+ proc{|v| [v].pack("c").unpack("C")[0]}],
+ ["unsigned short",
+ "H",
+ proc{|v| [v].pack("S").unpack("s")[0]},
+ proc{|v| [v].pack("s").unpack("S")[0]},
+ "H",
+ proc{|v| [v].pack("S").unpack("s")[0]},
+ proc{|v| [v].pack("s").unpack("S")[0]}],
+ ["unsigned int",
+ "I",
+ proc{|v| [v].pack("I").unpack("i")[0]},
+ proc{|v| [v].pack("i").unpack("I")[0]},
+ "I",
+ proc{|v| [v].pack("I").unpack("i")[0]},
+ proc{|v| [v].pack("i").unpack("I")[0]}],
+ ["unsigned long",
+ "L",
+ proc{|v| [v].pack("L").unpack("l")[0]},
+ proc{|v| [v].pack("l").unpack("L")[0]},
+ "L",
+ proc{|v| [v].pack("L").unpack("l")[0]},
+ proc{|v| [v].pack("l").unpack("L")[0]}],
+ ["unsigned char ref",
+ "c",
+ proc{|v| [v].pack("C").unpack("c")[0]},
+ proc{|v| [v].pack("c").unpack("C")[0]},
+ nil, nil, nil],
+ ["unsigned int ref",
+ "i",
+ proc{|v| [v].pack("I").unpack("i")[0]},
+ proc{|v| [v].pack("i").unpack("I")[0]},
+ nil, nil, nil],
+ ["unsigned long ref",
+ "l",
+ proc{|v| [v].pack("L").unpack("l")[0]},
+ proc{|v| [v].pack("l").unpack("L")[0]},
+ nil, nil, nil],
+ ["char ref", "c", nil, nil,
+ nil, nil, nil],
+ ["short ref", "h", nil, nil,
+ nil, nil, nil],
+ ["int ref", "i", nil, nil,
+ nil, nil, nil],
+ ["long ref", "l", nil, nil,
+ nil, nil, nil],
+ ["float ref", "f", nil, nil,
+ nil, nil, nil],
+ ["double ref","d", nil, nil,
+ nil, nil, nil],
+ ["char", "C", nil, nil,
+ "C", nil, nil],
+ ["short", "H", nil, nil,
+ "H", nil, nil],
+ ["int", "I", nil, nil,
+ "I", nil, nil],
+ ["long", "L", nil, nil,
+ "L", nil, nil],
+ ["float", "F", nil, nil,
+ "F", nil, nil],
+ ["double", "D", nil, nil,
+ "D", nil, nil],
+ [/^char\s*\*$/,"s",nil, nil,
+ "S",nil, nil],
+ [/^const char\s*\*$/,"S",nil, nil,
+ "S",nil, nil],
+ [/^.+\*$/, "P", nil, nil,
+ "P", nil, nil],
+ [/^.+\[\]$/, "a", nil, nil,
+ "a", nil, nil],
+ ["void", "0", nil, nil,
+ nil, nil, nil],
+ ]
+
+ def initialize
+ init_types()
+ end
+
+ def typealias(ty1, ty2, enc=nil, dec=nil, ty3=nil, senc=nil, sdec=nil)
+ @TYDEFS.unshift([ty1, ty2, enc, dec, ty3, senc, sdec])
+ end
+
+ def init_types
+ @TYDEFS = TYPES.dup
+ end
+
+ def encode_argument_type(alias_type)
+ proc_encode = nil
+ proc_decode = nil
+ @TYDEFS.each{|aty,ty,enc,dec,_,_,_|
+ if( (aty.is_a?(Regexp) && (aty =~ alias_type)) || (aty == alias_type) )
+ alias_type = alias_type.gsub(aty,ty) if ty
+ alias_type.strip! if alias_type
+ if( proc_encode )
+ if( enc )
+ conv1 = proc_encode
+ proc_encode = proc{|v| enc.call(conv1.call(v))}
+ end
+ else
+ if( enc )
+ proc_encode = enc
+ end
+ end
+ if( proc_decode )
+ if( dec )
+ conv2 = proc_decode
+ proc_decode = proc{|v| dec.call(conv2.call(v))}
+ end
+ else
+ if( dec )
+ proc_decode = dec
+ end
+ end
+ end
+ }
+ return [alias_type, proc_encode, proc_decode]
+ end
+
+ def encode_return_type(ty)
+ ty, enc, dec = encode_argument_type(ty)
+ return [ty, enc, dec]
+ end
+
+ def encode_struct_type(alias_type)
+ proc_encode = nil
+ proc_decode = nil
+ @TYDEFS.each{|aty,_,_,_,ty,enc,dec|
+ if( (aty.is_a?(Regexp) && (aty =~ alias_type)) || (aty == alias_type) )
+ alias_type = alias_type.gsub(aty,ty) if ty
+ alias_type.strip! if alias_type
+ if( proc_encode )
+ if( enc )
+ conv1 = proc_encode
+ proc_encode = proc{|v| enc.call(conv1.call(v))}
+ end
+ else
+ if( enc )
+ proc_encode = enc
+ end
+ end
+ if( proc_decode )
+ if( dec )
+ conv2 = proc_decode
+ proc_decode = proc{|v| dec.call(conv2.call(v))}
+ end
+ else
+ if( dec )
+ proc_decode = dec
+ end
+ end
+ end
+ }
+ return [alias_type, proc_encode, proc_decode]
+ end
+ end # end of Types
+end
diff --git a/ruby_1_8_6/ext/dl/lib/dl/win32.rb b/ruby_1_8_6/ext/dl/lib/dl/win32.rb
new file mode 100644
index 0000000000..0fed47c324
--- /dev/null
+++ b/ruby_1_8_6/ext/dl/lib/dl/win32.rb
@@ -0,0 +1,25 @@
+# -*- ruby -*-
+
+require 'dl'
+
+class Win32API
+ DLL = {}
+
+ def initialize(dllname, func, import, export = "0")
+ prototype = (export + import.to_s).tr("VPpNnLlIi", "0SSI").sub(/^(.)0*$/, '\1')
+ handle = DLL[dllname] ||= DL::Handle.new(dllname)
+ @sym = handle.sym(func, prototype)
+ end
+
+ def call(*args)
+ import = @sym.proto.split("", 2)[1]
+ args.each_with_index do |x, i|
+ args[i] = nil if x == 0 and import[i] == ?S
+ args[i], = [x].pack("I").unpack("i") if import[i] == ?I
+ end
+ ret, = @sym.call(*args)
+ return ret || 0
+ end
+
+ alias Call call
+end