summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog4
-rw-r--r--ext/dl/lib/dl/import.rb85
-rw-r--r--ext/dl/lib/dl/struct.rb107
-rw-r--r--ext/dl/lib/dl/types.rb237
4 files changed, 292 insertions, 141 deletions
diff --git a/ChangeLog b/ChangeLog
index 6125b5e27c..36b0534f19 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+Fri Apr 5 05:07:28 2002 Takaaki Tateishi <ttate@kt.jaist.ac.jp>
+
+ * ext/dl: Add dl/struct.rb.
+
Thu Apr 4 14:08:52 2002 Takaaki Tateishi <ttate@kt.jaist.ac.jp>
* ext/dl/lib/dl/import.rb: Get rid of ineffective
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 = []
@@ -41,14 +53,21 @@ module DL
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