rubysl-dl 0.0.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,149 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'dl'
4
+ require 'dl/import'
5
+
6
+ module DL
7
+ module Importable
8
+ module Internal
9
+ def define_struct(contents)
10
+ init_types()
11
+ Struct.new(@types, contents)
12
+ end
13
+ alias struct define_struct
14
+
15
+ def define_union(contents)
16
+ init_types()
17
+ Union.new(@types, contents)
18
+ end
19
+ alias union define_union
20
+
21
+ class Memory
22
+ def initialize(ptr, names, ty, len, enc, dec)
23
+ @ptr = ptr
24
+ @names = names
25
+ @ty = ty
26
+ @len = len
27
+ @enc = enc
28
+ @dec = dec
29
+
30
+ # define methods
31
+ @names.each{|name|
32
+ instance_eval [
33
+ "def #{name}",
34
+ " v = @ptr[\"#{name}\"]",
35
+ " if( @len[\"#{name}\"] )",
36
+ " v = v.collect{|x| @dec[\"#{name}\"] ? @dec[\"#{name}\"].call(x) : x }",
37
+ " else",
38
+ " v = @dec[\"#{name}\"].call(v) if @dec[\"#{name}\"]",
39
+ " end",
40
+ " return v",
41
+ "end",
42
+ "def #{name}=(v)",
43
+ " if( @len[\"#{name}\"] )",
44
+ " v = v.collect{|x| @enc[\"#{name}\"] ? @enc[\"#{name}\"].call(x) : x }",
45
+ " else",
46
+ " v = @enc[\"#{name}\"].call(v) if @enc[\"#{name}\"]",
47
+ " end",
48
+ " @ptr[\"#{name}\"] = v",
49
+ " return v",
50
+ "end",
51
+ ].join("\n")
52
+ }
53
+ end
54
+
55
+ def to_ptr
56
+ return @ptr
57
+ end
58
+
59
+ def size
60
+ return @ptr.size
61
+ end
62
+ end
63
+
64
+ class Struct
65
+ def initialize(types, contents)
66
+ @names = []
67
+ @ty = {}
68
+ @len = {}
69
+ @enc = {}
70
+ @dec = {}
71
+ @size = 0
72
+ @tys = ""
73
+ @types = types
74
+ parse(contents)
75
+ end
76
+
77
+ def size
78
+ return @size
79
+ end
80
+
81
+ def members
82
+ return @names
83
+ end
84
+
85
+ # ptr must be a PtrData object.
86
+ def new(ptr)
87
+ ptr.struct!(@tys, *@names)
88
+ mem = Memory.new(ptr, @names, @ty, @len, @enc, @dec)
89
+ return mem
90
+ end
91
+
92
+ def malloc(size = nil)
93
+ if( !size )
94
+ size = @size
95
+ end
96
+ ptr = DL::malloc(size)
97
+ return new(ptr)
98
+ end
99
+
100
+ def parse(contents)
101
+ contents.each{|elem|
102
+ name,ty,num,enc,dec = parse_elem(elem)
103
+ @names.push(name)
104
+ @ty[name] = ty
105
+ @len[name] = num
106
+ @enc[name] = enc
107
+ @dec[name] = dec
108
+ if( num )
109
+ @tys += "#{ty}#{num}"
110
+ else
111
+ @tys += ty
112
+ end
113
+ }
114
+ @size = DL.sizeof(@tys)
115
+ end
116
+
117
+ def parse_elem(elem)
118
+ elem.strip!
119
+ case elem
120
+ when /^([\w\d_\*]+)([\*\s]+)([\w\d_]+)$/
121
+ ty = ($1 + $2).strip
122
+ name = $3
123
+ num = nil;
124
+ when /^([\w\d_\*]+)([\*\s]+)([\w\d_]+)\[(\d+)\]$/
125
+ ty = ($1 + $2).strip
126
+ name = $3
127
+ num = $4.to_i
128
+ else
129
+ raise(RuntimeError, "invalid element: #{elem}")
130
+ end
131
+ ty,enc,dec = @types.encode_struct_type(ty)
132
+ if( !ty )
133
+ raise(TypeError, "unsupported type: #{ty}")
134
+ end
135
+ return [name,ty,num,enc,dec]
136
+ end
137
+ end # class Struct
138
+
139
+ class Union < Struct
140
+ def new
141
+ ptr = DL::malloc(@size)
142
+ ptr.union!(@tys, *@names)
143
+ mem = Memory.new(ptr, @names, @ty, @len, @enc, @dec)
144
+ return mem
145
+ end
146
+ end
147
+ end # module Internal
148
+ end # module Importable
149
+ end # module DL
@@ -0,0 +1,245 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'dl'
4
+
5
+ module DL
6
+ class Types
7
+ TYPES = [
8
+ # FORMAT:
9
+ # ["alias name",
10
+ # "type name", encoding_method, decoding_method, for function prototypes
11
+ # "type name", encoding_method, decoding_method] for structures (not implemented)
12
+
13
+ # for Windows
14
+ ["DWORD", "unsigned long", nil, nil,
15
+ "unsigned long", nil, nil],
16
+ ["PDWORD", "unsigned long *", nil, nil,
17
+ "unsigned long *", nil, nil],
18
+ ["WORD", "unsigned short", nil, nil,
19
+ "unsigned short", nil, nil],
20
+ ["PWORD", "unsigned int *", nil, nil,
21
+ "unsigned int *", nil, nil],
22
+ ["BYTE", "unsigned char", nil, nil,
23
+ "unsigned char", nil, nil],
24
+ ["PBYTE", "unsigned char *", nil, nil,
25
+ "unsigned char *", nil, nil],
26
+ ["BOOL", "ibool", nil, nil,
27
+ "ibool", nil, nil],
28
+ ["ATOM", "int", nil, nil,
29
+ "int", nil, nil],
30
+ ["BYTE", "unsigned char", nil, nil,
31
+ "unsigned char", nil, nil],
32
+ ["PBYTE", "unsigned char *", nil, nil,
33
+ "unsigned char *", nil, nil],
34
+ ["UINT", "unsigned int", nil, nil,
35
+ "unsigned int", nil, nil],
36
+ ["ULONG", "unsigned long", nil, nil,
37
+ "unsigned long", nil, nil],
38
+ ["UCHAR", "unsigned char", nil, nil,
39
+ "unsigned char", nil, nil],
40
+ ["HANDLE", "unsigned long", nil, nil,
41
+ "unsigned long", nil, nil],
42
+ ["PHANDLE","void*", nil, nil,
43
+ "void*", nil, nil],
44
+ ["PVOID", "void*", nil, nil,
45
+ "void*", nil, nil],
46
+ ["LPCSTR", "char*", nil, nil,
47
+ "char*", nil, nil],
48
+ ["HDC", "unsigned int", nil, nil,
49
+ "unsigned int", nil, nil],
50
+ ["HWND", "unsigned int", nil, nil,
51
+ "unsigned int", nil, nil],
52
+
53
+ # Others
54
+ ["uint", "unsigned int", nil, nil,
55
+ "unsigned int", nil, nil],
56
+ ["u_int", "unsigned int", nil, nil,
57
+ "unsigned int", nil, nil],
58
+ ["ulong", "unsigned long", nil, nil,
59
+ "unsigned long", nil, nil],
60
+ ["u_long", "unsigned long", nil, nil,
61
+ "unsigned long", nil, nil],
62
+
63
+ # DL::Importable primitive types
64
+ ["ibool",
65
+ "I",
66
+ proc{|v| v ? 1 : 0},
67
+ proc{|v| (v != 0) ? true : false},
68
+ "I",
69
+ proc{|v| v ? 1 : 0 },
70
+ proc{|v| (v != 0) ? true : false} ],
71
+ ["cbool",
72
+ "C",
73
+ proc{|v| v ? 1 : 0},
74
+ proc{|v| (v != 0) ? true : false},
75
+ "C",
76
+ proc{|v,len| v ? 1 : 0},
77
+ proc{|v,len| (v != 0) ? true : false}],
78
+ ["lbool",
79
+ "L",
80
+ proc{|v| v ? 1 : 0},
81
+ proc{|v| (v != 0) ? true : false},
82
+ "L",
83
+ proc{|v,len| v ? 1 : 0},
84
+ proc{|v,len| (v != 0) ? true : false}],
85
+ ["unsigned char",
86
+ "C",
87
+ proc{|v| [v].pack("C").unpack("c")[0]},
88
+ proc{|v| [v].pack("c").unpack("C")[0]},
89
+ "C",
90
+ proc{|v| [v].pack("C").unpack("c")[0]},
91
+ proc{|v| [v].pack("c").unpack("C")[0]}],
92
+ ["unsigned short",
93
+ "H",
94
+ proc{|v| [v].pack("S").unpack("s")[0]},
95
+ proc{|v| [v].pack("s").unpack("S")[0]},
96
+ "H",
97
+ proc{|v| [v].pack("S").unpack("s")[0]},
98
+ proc{|v| [v].pack("s").unpack("S")[0]}],
99
+ ["unsigned int",
100
+ "I",
101
+ proc{|v| [v].pack("I").unpack("i")[0]},
102
+ proc{|v| [v].pack("i").unpack("I")[0]},
103
+ "I",
104
+ proc{|v| [v].pack("I").unpack("i")[0]},
105
+ proc{|v| [v].pack("i").unpack("I")[0]}],
106
+ ["unsigned long",
107
+ "L",
108
+ proc{|v| [v].pack("L").unpack("l")[0]},
109
+ proc{|v| [v].pack("l").unpack("L")[0]},
110
+ "L",
111
+ proc{|v| [v].pack("L").unpack("l")[0]},
112
+ proc{|v| [v].pack("l").unpack("L")[0]}],
113
+ ["unsigned char ref",
114
+ "c",
115
+ proc{|v| [v].pack("C").unpack("c")[0]},
116
+ proc{|v| [v].pack("c").unpack("C")[0]},
117
+ nil, nil, nil],
118
+ ["unsigned int ref",
119
+ "i",
120
+ proc{|v| [v].pack("I").unpack("i")[0]},
121
+ proc{|v| [v].pack("i").unpack("I")[0]},
122
+ nil, nil, nil],
123
+ ["unsigned long ref",
124
+ "l",
125
+ proc{|v| [v].pack("L").unpack("l")[0]},
126
+ proc{|v| [v].pack("l").unpack("L")[0]},
127
+ nil, nil, nil],
128
+ ["char ref", "c", nil, nil,
129
+ nil, nil, nil],
130
+ ["short ref", "h", nil, nil,
131
+ nil, nil, nil],
132
+ ["int ref", "i", nil, nil,
133
+ nil, nil, nil],
134
+ ["long ref", "l", nil, nil,
135
+ nil, nil, nil],
136
+ ["float ref", "f", nil, nil,
137
+ nil, nil, nil],
138
+ ["double ref","d", nil, nil,
139
+ nil, nil, nil],
140
+ ["char", "C", nil, nil,
141
+ "C", nil, nil],
142
+ ["short", "H", nil, nil,
143
+ "H", nil, nil],
144
+ ["int", "I", nil, nil,
145
+ "I", nil, nil],
146
+ ["long", "L", nil, nil,
147
+ "L", nil, nil],
148
+ ["float", "F", nil, nil,
149
+ "F", nil, nil],
150
+ ["double", "D", nil, nil,
151
+ "D", nil, nil],
152
+ [/^char\s*\*$/,"s",nil, nil,
153
+ "S",nil, nil],
154
+ [/^const char\s*\*$/,"S",nil, nil,
155
+ "S",nil, nil],
156
+ [/^.+\*$/, "P", nil, nil,
157
+ "P", nil, nil],
158
+ [/^.+\[\]$/, "a", nil, nil,
159
+ "a", nil, nil],
160
+ ["void", "0", nil, nil,
161
+ nil, nil, nil],
162
+ ]
163
+
164
+ def initialize
165
+ init_types()
166
+ end
167
+
168
+ def typealias(ty1, ty2, enc=nil, dec=nil, ty3=nil, senc=nil, sdec=nil)
169
+ @TYDEFS.unshift([ty1, ty2, enc, dec, ty3, senc, sdec])
170
+ end
171
+
172
+ def init_types
173
+ @TYDEFS = TYPES.dup
174
+ end
175
+
176
+ def encode_argument_type(alias_type)
177
+ proc_encode = nil
178
+ proc_decode = nil
179
+ @TYDEFS.each{|aty,ty,enc,dec,_,_,_|
180
+ if( (aty.is_a?(Regexp) && (aty =~ alias_type)) || (aty == alias_type) )
181
+ alias_type = alias_type.gsub(aty,ty) if ty
182
+ alias_type.strip! if alias_type
183
+ if( proc_encode )
184
+ if( enc )
185
+ conv1 = proc_encode
186
+ proc_encode = proc{|v| enc.call(conv1.call(v))}
187
+ end
188
+ else
189
+ if( enc )
190
+ proc_encode = enc
191
+ end
192
+ end
193
+ if( proc_decode )
194
+ if( dec )
195
+ conv2 = proc_decode
196
+ proc_decode = proc{|v| dec.call(conv2.call(v))}
197
+ end
198
+ else
199
+ if( dec )
200
+ proc_decode = dec
201
+ end
202
+ end
203
+ end
204
+ }
205
+ return [alias_type, proc_encode, proc_decode]
206
+ end
207
+
208
+ def encode_return_type(ty)
209
+ ty, enc, dec = encode_argument_type(ty)
210
+ return [ty, enc, dec]
211
+ end
212
+
213
+ def encode_struct_type(alias_type)
214
+ proc_encode = nil
215
+ proc_decode = nil
216
+ @TYDEFS.each{|aty,_,_,_,ty,enc,dec|
217
+ if( (aty.is_a?(Regexp) && (aty =~ alias_type)) || (aty == alias_type) )
218
+ alias_type = alias_type.gsub(aty,ty) if ty
219
+ alias_type.strip! if alias_type
220
+ if( proc_encode )
221
+ if( enc )
222
+ conv1 = proc_encode
223
+ proc_encode = proc{|v| enc.call(conv1.call(v))}
224
+ end
225
+ else
226
+ if( enc )
227
+ proc_encode = enc
228
+ end
229
+ end
230
+ if( proc_decode )
231
+ if( dec )
232
+ conv2 = proc_decode
233
+ proc_decode = proc{|v| dec.call(conv2.call(v))}
234
+ end
235
+ else
236
+ if( dec )
237
+ proc_decode = dec
238
+ end
239
+ end
240
+ end
241
+ }
242
+ return [alias_type, proc_encode, proc_decode]
243
+ end
244
+ end # end of Types
245
+ end
@@ -0,0 +1,25 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'dl'
4
+
5
+ class Win32API
6
+ DLL = {}
7
+
8
+ def initialize(dllname, func, import, export = "0")
9
+ prototype = (export + import.to_s).tr("VPpNnLlIi", "0SSI").sub(/^(.)0*$/, '\1')
10
+ handle = DLL[dllname] ||= DL::Handle.new(dllname)
11
+ @sym = handle.sym(func, prototype)
12
+ end
13
+
14
+ def call(*args)
15
+ import = @sym.proto.split("", 2)[1]
16
+ args.each_with_index do |x, i|
17
+ args[i] = nil if x == 0 and import[i] == ?S
18
+ args[i], = [x].pack("I").unpack("i") if import[i] == ?I
19
+ end
20
+ ret, = @sym.call(*args)
21
+ return ret || 0
22
+ end
23
+
24
+ alias Call call
25
+ end
@@ -0,0 +1,69 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'mkmf'
4
+ $:.unshift File.dirname(__FILE__)
5
+ require 'type'
6
+ require 'dlconfig'
7
+
8
+ if name = ARGV.shift
9
+ OUTPUT = File.open name, "wb"
10
+ at_exit { OUTPUT.close }
11
+ else
12
+ OUTPUT = STDOUT
13
+ end
14
+
15
+ def output_arg(x,i)
16
+ "args[#{i}].#{DLTYPE[x][:stmem]}"
17
+ end
18
+
19
+ def output_args(types)
20
+ t = []
21
+ types[1..-1].each_with_index{|x,i| t.push(output_arg(x,i))}
22
+ t.join(",")
23
+ end
24
+
25
+ def output_callfunc(types)
26
+ t = types[0]
27
+ stmem = DLTYPE[t][:stmem]
28
+ ctypes = types2ctypes(types)
29
+ if( t == VOID )
30
+ callstm = "(*f)(#{output_args(types)})"
31
+ else
32
+ callstm = "ret.#{stmem} = (*f)(#{output_args(types)})"
33
+ end
34
+ [ "{",
35
+ "#{ctypes[0]} (*f)(#{ctypes[1..-1].join(',')}) = func;",
36
+ "#{callstm};",
37
+ "}"].join(" ")
38
+ end
39
+
40
+ def output_case(types)
41
+ num = types2num(types)
42
+ callfunc_stm = output_callfunc(types)
43
+ <<EOF
44
+ case #{num}:
45
+ #ifdef DEBUG
46
+ OUTPUT.printf("#{callfunc_stm}\\n");
47
+ #endif
48
+ #{callfunc_stm};
49
+ break;
50
+ EOF
51
+ end
52
+
53
+ def rec_output(types = [VOID])
54
+ OUTPUT.print output_case(types)
55
+ if( types.length <= MAX_ARG )
56
+ DLTYPE.keys.sort.each{|t|
57
+ if( t != VOID && DLTYPE[t][:sym] )
58
+ rec_output(types + [t])
59
+ end
60
+ }
61
+ end
62
+ end
63
+
64
+ DLTYPE.keys.sort.each{|t|
65
+ if( DLTYPE[t][:sym] )
66
+ $stderr.printf(" #{DLTYPE[t][:ctype]}\n")
67
+ rec_output([t])
68
+ end
69
+ }