rubysl-dl 0.0.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
+ }