From 7d711b817e62eb6c8dee01ea2283fcb1ad90f8ac Mon Sep 17 00:00:00 2001 From: ttate Date: Tue, 2 Apr 2002 10:56:13 +0000 Subject: Add ruby-dl git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2324 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/dl/lib/dl/import.rb | 228 ++++++++++++++++++++++++++++++++++++++++++++++++ ext/dl/lib/dl/win32.rb | 26 ++++++ 2 files changed, 254 insertions(+) create mode 100644 ext/dl/lib/dl/import.rb create mode 100644 ext/dl/lib/dl/win32.rb (limited to 'ext/dl/lib/dl') diff --git a/ext/dl/lib/dl/import.rb b/ext/dl/lib/dl/import.rb new file mode 100644 index 0000000000..78f6a2b785 --- /dev/null +++ b/ext/dl/lib/dl/import.rb @@ -0,0 +1,228 @@ +# -*- ruby -*- + +require 'dl' + +module DL + module Importable + LIB_MAP = {} + + module Internal + 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 + + # example: + # extern "int strlen(char*)" + # + def extern(proto) + proto = proto.gsub(/\s+/, " ").strip + case proto + when /^([\d\w\*_\s]+)\(([\d\w\*_\s\,\[\]]*)\)$/ + ret = $1 + args = $2 + ret = ret.split(/\s+/) + args = args.split(/\s*,\s*/) + func = ret.pop + ret = ret.join(" ") + return import(func, ret, args) + else + raise(RuntimeError,"can't parse the function prototype: #{proto}") + end + end + + # example: + # import("get_length", "int", ["void*", "int"]) + # + def import(name, rettype, argtypes = nil) + if( !defined?(@SYM) ) + @SYM = {} + end + @LIBS.each{|lib| + rty,_,rdec = encode_type(rettype) + ty,enc,dec = encode_types(argtypes) + symty = rty + ty + + begin + sym = lib[name, symty] + rescue + next + end + + 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( $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, + " @retval = rdec.call(r)", + " @args = dec.call(rs)", + " return @retval", + "end", + "module_function :#{mname}", + ].join("\n") + + return @SYM[mname] + } + raise(RuntimeError, "can't find #{name}.") + end + + def _args_ + return @args + end + + 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 = proc{|v| v} + dec = proc{|v| v} + @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( c1 ) + conv1 = enc + enc = proc{|v| c1.call(conv1.call(v))} + end + if( c2 ) + conv2 = dec + dec = proc{|v| c2.call(conv2.call(v))} + 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) + encty = [] + enc = proc{|v| v} + dec = proc{|v| v} + tys.each_with_index{|ty,idx| + ty,c1,c2 = encode_type(ty) + encty.push(ty) + conv1 = enc + enc = proc{|v| v = conv1.call(v); v[idx] = c1.call(v[idx]); v} + conv2 = dec + dec = proc{|v| v = conv2.call(v); v[idx] = c2.call(v[idx]); v} + } + return [encty.join, enc, dec] + end + + def check_type + if( !defined?(@TYDEFS) ) + init_type + end + end + + def init_type + @TYDEFS = [ + # for Windows + ["DWORD", "unsigned long", nil, nil], + ["PDWORD", "unsigned long *", nil, nil], + ["WORD", "unsigned int", nil, nil], + ["PWORD", "unsigned int *", nil, nil], + ["BOOL", "ibool", nil, nil], + ["ATOM", "int", nil, nil], + ["BYTE", "unsigned char", nil, nil], + ["PBYTE", "unsigned char *", nil, nil], + ["UINT", "unsigned int", nil, nil], + ["ULONG", "unsigned long", nil, nil], + ["UCHAR", "unsigned char", nil, nil], + ["HANDLE", "unsigned long", nil, nil], + ["PHANDLE","void*", nil, nil], + ["PVOID", "void*", nil, nil], + ["LPCSTR", "char*", nil, nil], + + # Others + ["uint", "unsigned int", nil, nil], + ["u_int", "unsigned int", nil, nil], + ["ulong", "unsigned long", nil, nil], + ["u_long", "unsigned long", nil, nil], + + # DL::Importable primitive types + ["ibool", "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}], + ["lbool", "L", + proc{|v| v ? 1 : 0}, + proc{|v| (v != 0) ? true : false}], + ["unsigned char", "I", + proc{|v| [v].pack("C").unpack("c")[0]}, + proc{|v| [v].pack("c").unpack("C")[0]}], + ["unsigned int", "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]}], + ["unsigned char ref", "i", + proc{|v| [v].pack("C").unpack("c")[0]}, + proc{|v| [v].pack("c").unpack("C")[0]}], + ["unsigned int ref", "i", + proc{|v| [v].pack("I").unpack("i")[0]}, + proc{|v| [v].pack("i").unpack("I")[0]}], + ["unsigned long ref", "l", + proc{|v| [v].pack("L").unpack("l")[0]}, + proc{|v| [v].pack("l").unpack("L")[0]}], + ["char ref", "c", nil, nil], + ["short ref", "h", nil, nil], + ["int ref", "i", nil, nil], + ["long ref", "l", nil, nil], + ["float ref", "f", nil, nil], + ["double ref","d", nil, nil], + ["char", "C", nil, nil], + ["short", "H", nil, nil], + ["int", "I", nil, nil], + ["long", "L", nil, nil], + ["float", "F", nil, nil], + ["double", "D", nil, nil], + [/.+\*/, "P", nil, nil], + [/.+\[\]/, "a", nil, nil], + ["void", "0", nil, nil], + ] + end + end # end of Internal + include Internal + end # end of Importable +end diff --git a/ext/dl/lib/dl/win32.rb b/ext/dl/lib/dl/win32.rb new file mode 100644 index 0000000000..b507be5fde --- /dev/null +++ b/ext/dl/lib/dl/win32.rb @@ -0,0 +1,26 @@ +# -*- ruby -*- + +require 'dl' + +class Win32API + LIBRARY = {} + + attr_reader :val, :args + + def initialize(lib, func, args, ret) + LIBRARY[lib] ||= DL.dlopen(lib) + ty = (ret + args).tr('V','0') + @sym = LIBRARY[lib].sym(func, ty) + @__dll__ = LIBRARY[lib].to_i + @__dllname__ = lib + @__proc__ = @sym.to_i + @val = nil + @args = [] + end + + def call(*args) + @val,@args = @sym.call(*args) + return @val + end + alias Call call +end -- cgit v1.2.3