rbind 0.0.1
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.
- data/lib/rbind.rb +5 -0
- data/lib/rbind/.default_parser.rb.swp +0 -0
- data/lib/rbind/.generator_c.rb.swp +0 -0
- data/lib/rbind/core.rb +13 -0
- data/lib/rbind/core/.rbase.rb.swp +0 -0
- data/lib/rbind/core/.rclass.rb.swp +0 -0
- data/lib/rbind/core/.rdata_type.rb.swp +0 -0
- data/lib/rbind/core/.roperation.rb.swp +0 -0
- data/lib/rbind/core/rattribute.rb +45 -0
- data/lib/rbind/core/rbase.rb +172 -0
- data/lib/rbind/core/rclass.rb +149 -0
- data/lib/rbind/core/rconst.rb +35 -0
- data/lib/rbind/core/rdata_type.rb +93 -0
- data/lib/rbind/core/renum.rb +5 -0
- data/lib/rbind/core/rgetter.rb +19 -0
- data/lib/rbind/core/rnamespace.rb +305 -0
- data/lib/rbind/core/roperation.rb +128 -0
- data/lib/rbind/core/rparameter.rb +40 -0
- data/lib/rbind/core/rsetter.rb +20 -0
- data/lib/rbind/core/rstruct.rb +87 -0
- data/lib/rbind/default_parser.rb +253 -0
- data/lib/rbind/generator_c.rb +352 -0
- data/lib/rbind/generator_ruby.rb +357 -0
- data/lib/rbind/logger.rb +13 -0
- data/lib/rbind/rbind.rb +68 -0
- data/lib/rbind/templates/c/CMakeLists.txt +11 -0
- data/lib/rbind/templates/c/consts.h +5 -0
- data/lib/rbind/templates/c/conversions.cc +4 -0
- data/lib/rbind/templates/c/conversions.hpp +10 -0
- data/lib/rbind/templates/c/find_package.txt +5 -0
- data/lib/rbind/templates/c/operation_wrapper.cc +15 -0
- data/lib/rbind/templates/c/operations.cc +23 -0
- data/lib/rbind/templates/c/operations.h +20 -0
- data/lib/rbind/templates/c/type_conversion.cc +45 -0
- data/lib/rbind/templates/c/type_conversion.hpp +5 -0
- data/lib/rbind/templates/c/type_delete.h +14 -0
- data/lib/rbind/templates/c/type_typedef.h +2 -0
- data/lib/rbind/templates/c/type_wrapper.h +12 -0
- data/lib/rbind/templates/c/types.cc +6 -0
- data/lib/rbind/templates/c/types.h +17 -0
- data/lib/rbind/templates/ruby/rbind.rb +44 -0
- data/lib/rbind/templates/ruby/rmethod.rb +12 -0
- data/lib/rbind/templates/ruby/rnamespace.rb +7 -0
- data/lib/rbind/templates/ruby/rstatic_method.rb +5 -0
- data/lib/rbind/templates/ruby/rtype.rb +77 -0
- data/lib/rbind/templates/ruby/rtype_constructor.rb +4 -0
- data/rbind.gemspec +17 -0
- metadata +101 -0
@@ -0,0 +1,19 @@
|
|
1
|
+
|
2
|
+
module Rbind
|
3
|
+
class RGetter < ROperation
|
4
|
+
attr_reader :attribute
|
5
|
+
|
6
|
+
def initialize(attr)
|
7
|
+
@attribute = attr
|
8
|
+
super("get_#{attr.name}",attr.type)
|
9
|
+
end
|
10
|
+
|
11
|
+
def attribute?
|
12
|
+
true
|
13
|
+
end
|
14
|
+
|
15
|
+
def signature
|
16
|
+
attribute.signature
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,305 @@
|
|
1
|
+
|
2
|
+
module Rbind
|
3
|
+
class RNamespace< RDataType
|
4
|
+
class << self
|
5
|
+
attr_accessor :default_type_names
|
6
|
+
end
|
7
|
+
self.default_type_names = [:int,:int64,:bool,:double,:float,:void,:char,:size_t]
|
8
|
+
|
9
|
+
attr_reader :operations
|
10
|
+
attr_reader :operation_alias
|
11
|
+
attr_reader :consts
|
12
|
+
attr_reader :used_namespaces
|
13
|
+
attr_accessor :root
|
14
|
+
|
15
|
+
def initialize(name,*flags)
|
16
|
+
@consts = Hash.new
|
17
|
+
@types = Hash.new
|
18
|
+
@operations = Hash.new{|hash,key| hash[key] = Array.new}
|
19
|
+
@operation_alias = Hash.new{|hash,key| hash[key] = Array.new}
|
20
|
+
@used_namespaces = Hash.new
|
21
|
+
super(name,*flags)
|
22
|
+
end
|
23
|
+
|
24
|
+
def root?
|
25
|
+
!!root
|
26
|
+
end
|
27
|
+
|
28
|
+
def constructor?
|
29
|
+
false
|
30
|
+
end
|
31
|
+
|
32
|
+
def types
|
33
|
+
@types.values
|
34
|
+
end
|
35
|
+
|
36
|
+
def delete_type(name)
|
37
|
+
ns = RBase.namespace(name)
|
38
|
+
if ns
|
39
|
+
type(ns).delete_type(RBase.basename(name))
|
40
|
+
else
|
41
|
+
@types.delete(name)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def use_namespace(namespace)
|
46
|
+
@used_namespaces[namespace.name] = namespace
|
47
|
+
end
|
48
|
+
|
49
|
+
def each_type(childs=true,&block)
|
50
|
+
if block_given?
|
51
|
+
types.each do |t|
|
52
|
+
yield t
|
53
|
+
t.each_type(&block) if childs && t.respond_to?(:each_type)
|
54
|
+
end
|
55
|
+
else
|
56
|
+
Enumerator.new(self,:each_type,childs)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def consts
|
61
|
+
@consts.values
|
62
|
+
end
|
63
|
+
|
64
|
+
def const(name,raise_ = true,search_owner = true)
|
65
|
+
c = if @consts.has_key?(name)
|
66
|
+
@consts[name]
|
67
|
+
else
|
68
|
+
if !!(ns = RBase.namespace(name))
|
69
|
+
t = type(ns,false)
|
70
|
+
t.const(RBase.basename(name),false,false) if t
|
71
|
+
end
|
72
|
+
end
|
73
|
+
c ||= begin
|
74
|
+
used_namespaces.values.each do |ns|
|
75
|
+
c = ns.const(name,false,false)
|
76
|
+
break if c
|
77
|
+
end
|
78
|
+
c
|
79
|
+
end
|
80
|
+
c ||= if search_owner && owner
|
81
|
+
owner.const(name,false)
|
82
|
+
end
|
83
|
+
raise RuntimeError,"#{full_name} has no const called #{name}" if raise_ && !c
|
84
|
+
end
|
85
|
+
|
86
|
+
def operations
|
87
|
+
@operations.values
|
88
|
+
end
|
89
|
+
|
90
|
+
def container?
|
91
|
+
true
|
92
|
+
end
|
93
|
+
|
94
|
+
def operation(name,raise_=true)
|
95
|
+
ops = @operations[name]
|
96
|
+
if(ops.size == 1)
|
97
|
+
ops.first
|
98
|
+
elsif ops.empty?
|
99
|
+
@operations.delete name
|
100
|
+
raise "#{full_name} has no operation called #{name}." if raise_
|
101
|
+
else
|
102
|
+
ops
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def operation?(name)
|
107
|
+
!!operation(name,false)
|
108
|
+
end
|
109
|
+
|
110
|
+
def add_operation(op)
|
111
|
+
op.owner = self
|
112
|
+
|
113
|
+
# make sure there is no name clash
|
114
|
+
other = @operations[op.name].find do |o|
|
115
|
+
o.cname == op.cname
|
116
|
+
end
|
117
|
+
other ||= @operation_alias[op.name].find do |o|
|
118
|
+
o.cname == op.cname
|
119
|
+
end
|
120
|
+
op.alias = if !other
|
121
|
+
op.alias
|
122
|
+
elsif op.alias
|
123
|
+
name = "#{op.alias}#{@operations[op.name].size+1}"
|
124
|
+
::Rbind.log.info "name clash: aliasing #{op.alias} --> #{name}"
|
125
|
+
name
|
126
|
+
else
|
127
|
+
name = "#{op.name}#{@operations[op.name].size+1}"
|
128
|
+
::Rbind.log.info "name clash: #{op.name} --> #{name}"
|
129
|
+
name
|
130
|
+
end
|
131
|
+
@operations[op.name] << op
|
132
|
+
@operation_alias[op.alias] << op if op.alias
|
133
|
+
op
|
134
|
+
end
|
135
|
+
|
136
|
+
def add_namespace(namespace)
|
137
|
+
names = namespace.split("::")
|
138
|
+
current_type = self
|
139
|
+
while !names.empty?
|
140
|
+
name = names.shift
|
141
|
+
temp = current_type.type(name,false,false)
|
142
|
+
current_type = if temp
|
143
|
+
temp
|
144
|
+
else
|
145
|
+
::Rbind.log.info "missing namespace: add #{current_type.full_name unless current_type.root?}::#{name}"
|
146
|
+
current_type.add_type(RNamespace.new(name))
|
147
|
+
end
|
148
|
+
end
|
149
|
+
current_type
|
150
|
+
end
|
151
|
+
|
152
|
+
def add_const(const)
|
153
|
+
if const(const.full_name,false,false)
|
154
|
+
raise ArgumentError,"#A const with the name #{const.full_name} already exists"
|
155
|
+
end
|
156
|
+
if const.namespace? && self.full_name != const.namespace
|
157
|
+
t=type(const.namespace,false)
|
158
|
+
t ||= add_namespace(const.namespace)
|
159
|
+
t.add_const(const)
|
160
|
+
else
|
161
|
+
const.owner = self
|
162
|
+
@consts[const.name] = const
|
163
|
+
end
|
164
|
+
const
|
165
|
+
end
|
166
|
+
|
167
|
+
def add_default_types
|
168
|
+
add_simple_types RNamespace.default_type_names
|
169
|
+
add_type ::Rbind::RDataType.new("uchar").cname("unsigned char")
|
170
|
+
add_type ::Rbind::RDataType.new("uint64").typedef("unsigned long long")
|
171
|
+
add_type ::Rbind::RDataType.new("c_string").cname("char *")
|
172
|
+
add_type ::Rbind::RDataType.new("const_c_string").cname("const char *")
|
173
|
+
end
|
174
|
+
|
175
|
+
def add_simple_type(name)
|
176
|
+
add_type(RDataType.new(name))
|
177
|
+
end
|
178
|
+
|
179
|
+
def add_simple_types(*names)
|
180
|
+
names.flatten!
|
181
|
+
names.each do |n|
|
182
|
+
add_simple_type(n)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def add_type(type)
|
187
|
+
raise ArgumentError, "wrong parmeter type #{type}" unless type.is_a? RDataType
|
188
|
+
if type(type.full_name,false,false)
|
189
|
+
raise ArgumentError,"A type with the name #{type.full_name} already exists"
|
190
|
+
end
|
191
|
+
# if self is not the right namespace
|
192
|
+
if type.namespace? && self.full_name != type.namespace && !(self.full_name =~/(.*)::#{type.namespace}/)
|
193
|
+
t=type(type.namespace,false)
|
194
|
+
t ||=add_namespace(type.namespace)
|
195
|
+
t.add_type(type)
|
196
|
+
else
|
197
|
+
type.owner = self
|
198
|
+
@types[type.name] = type
|
199
|
+
end
|
200
|
+
type
|
201
|
+
end
|
202
|
+
|
203
|
+
def type(name,raise_ = true,search_owner = true)
|
204
|
+
ptr = name.include?("*")
|
205
|
+
ref = name.include?("&")
|
206
|
+
if(ptr && ref)
|
207
|
+
raise ArgumentError,"given type is a reference and pointer at the same time: #{name}"
|
208
|
+
end
|
209
|
+
name = name.gsub("*","").gsub("&","")
|
210
|
+
name = name.chomp(" ")
|
211
|
+
t = if @types.has_key?(name)
|
212
|
+
@types[name]
|
213
|
+
else
|
214
|
+
if !!(ns = RBase.namespace(name))
|
215
|
+
ns = ns.split("::")
|
216
|
+
ns << RBase.basename(name)
|
217
|
+
t = type(ns.shift,false)
|
218
|
+
t.type(ns.join("::"),false,false) if t
|
219
|
+
end
|
220
|
+
end
|
221
|
+
t ||= begin
|
222
|
+
used_namespaces.values.each do |ns|
|
223
|
+
t = ns.type(name,false,false)
|
224
|
+
break if t
|
225
|
+
end
|
226
|
+
t
|
227
|
+
end
|
228
|
+
t ||= if search_owner && owner
|
229
|
+
owner.type(name,false)
|
230
|
+
end
|
231
|
+
raise RuntimeError,"#{full_name} has no type called #{name}" if raise_ && !t
|
232
|
+
if t && (ptr || ref)
|
233
|
+
t = t.clone
|
234
|
+
t.ref = ref
|
235
|
+
t.ptr = ptr
|
236
|
+
end
|
237
|
+
t
|
238
|
+
end
|
239
|
+
|
240
|
+
def pretty_print_name
|
241
|
+
"namespace #{full_name}#{" Flags: #{flags.join(", ")}" unless flags.empty?}"
|
242
|
+
end
|
243
|
+
|
244
|
+
def root?
|
245
|
+
!!root
|
246
|
+
end
|
247
|
+
|
248
|
+
def pretty_print(pp)
|
249
|
+
pp.text pretty_print_name
|
250
|
+
|
251
|
+
unless consts.empty?
|
252
|
+
pp.nest(2) do
|
253
|
+
pp.breakable
|
254
|
+
pp.text "Consts:"
|
255
|
+
pp.nest(2) do
|
256
|
+
consts.each do |c|
|
257
|
+
pp.breakable
|
258
|
+
pp.pp(c)
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
end
|
263
|
+
unless types.empty?
|
264
|
+
pp.nest(2) do
|
265
|
+
pp.breakable
|
266
|
+
pp.text "Types:"
|
267
|
+
pp.nest(2) do
|
268
|
+
types.each do |t|
|
269
|
+
pp.breakable
|
270
|
+
pp.pp(t)
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
unless operations.empty?
|
277
|
+
pp.nest(2) do
|
278
|
+
pp.breakable
|
279
|
+
pp.text "Operations:"
|
280
|
+
pp.nest(2) do
|
281
|
+
operations.each do |op|
|
282
|
+
op.each do |o|
|
283
|
+
pp.breakable
|
284
|
+
pp.pp(o)
|
285
|
+
end
|
286
|
+
end
|
287
|
+
end
|
288
|
+
end
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
def method_missing(m,*args)
|
293
|
+
t = type(m.to_s,false)
|
294
|
+
return t if t
|
295
|
+
|
296
|
+
op = operation(m.to_s,false)
|
297
|
+
return op if op
|
298
|
+
|
299
|
+
super
|
300
|
+
end
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
|
305
|
+
|
@@ -0,0 +1,128 @@
|
|
1
|
+
|
2
|
+
module Rbind
|
3
|
+
class ROperation < RBase
|
4
|
+
attr_accessor :return_type
|
5
|
+
attr_accessor :parameters
|
6
|
+
attr_accessor :cparameters
|
7
|
+
attr_accessor :base_class
|
8
|
+
attr_accessor :ambiguous_name
|
9
|
+
|
10
|
+
def initialize(name,return_type,*args)
|
11
|
+
super(name)
|
12
|
+
raise ArgumentError ,"wrong type #{return_type}" if return_type && !return_type.is_a?(RDataType)
|
13
|
+
@return_type = return_type
|
14
|
+
@parameters = args.flatten
|
15
|
+
@parameters.each do |para|
|
16
|
+
raise ArgumentError ,"wrong parameter type#{para}" if !para.is_a?(RParameter)
|
17
|
+
end
|
18
|
+
@cparameters = @parameters
|
19
|
+
end
|
20
|
+
|
21
|
+
def ==(other)
|
22
|
+
return false unless name == other.name
|
23
|
+
@parameters.each_with_index do |p,i|
|
24
|
+
return false if p != other.parameters[i]
|
25
|
+
end
|
26
|
+
true
|
27
|
+
end
|
28
|
+
|
29
|
+
# returns true if the operations is in inherit
|
30
|
+
# from one of the base classes
|
31
|
+
def inherit?
|
32
|
+
@base_class != @owner
|
33
|
+
end
|
34
|
+
|
35
|
+
def operator?
|
36
|
+
op = operator
|
37
|
+
op && op != '[]' && op != '()'
|
38
|
+
end
|
39
|
+
|
40
|
+
# for now returns true if the owner class
|
41
|
+
# has no constructor
|
42
|
+
def abstract?
|
43
|
+
!base_class.operation(base_class.name,false)
|
44
|
+
end
|
45
|
+
|
46
|
+
# operations with ambiguous name lookup due to multi inheritance
|
47
|
+
def ambiguous_name?
|
48
|
+
!!@ambiguous_name
|
49
|
+
end
|
50
|
+
|
51
|
+
def operator
|
52
|
+
name =~ /operator ?(.*)/
|
53
|
+
$1
|
54
|
+
end
|
55
|
+
|
56
|
+
def parameter(idx)
|
57
|
+
@parameters[idx]
|
58
|
+
end
|
59
|
+
|
60
|
+
def valid_flags
|
61
|
+
super << :S << :explicit
|
62
|
+
end
|
63
|
+
|
64
|
+
def static?
|
65
|
+
@flags.include?(:S)
|
66
|
+
end
|
67
|
+
|
68
|
+
def generate_signatures
|
69
|
+
s = "#{return_type.signature} " unless constructor?
|
70
|
+
s = "#{s}#{full_name}(#{parameters.map(&:signature).join(", ")})"
|
71
|
+
|
72
|
+
cs = if constructor?
|
73
|
+
owner.to_ptr.csignature if owner
|
74
|
+
else
|
75
|
+
if return_type.basic_type?
|
76
|
+
return_type.csignature
|
77
|
+
else
|
78
|
+
return_type.to_ptr.csignature
|
79
|
+
end
|
80
|
+
end
|
81
|
+
paras = cparameters.map do |p|
|
82
|
+
if p.type.basic_type?
|
83
|
+
p.csignature
|
84
|
+
else
|
85
|
+
tp = p.to_ptr
|
86
|
+
"#{tp.csignature}"
|
87
|
+
end
|
88
|
+
end.join(", ")
|
89
|
+
cs = "#{cs} #{cname}(#{paras})"
|
90
|
+
[s,cs]
|
91
|
+
end
|
92
|
+
|
93
|
+
def instance_method?
|
94
|
+
owner.is_a?(RStruct) && !constructor? && !static?
|
95
|
+
end
|
96
|
+
|
97
|
+
def owner=(obj)
|
98
|
+
super
|
99
|
+
@base_class ||=obj
|
100
|
+
@cparameters = if instance_method?
|
101
|
+
p = RParameter.new("rbind_obj",obj,nil,:IO)
|
102
|
+
[p] + @parameters
|
103
|
+
else
|
104
|
+
@parameters
|
105
|
+
end
|
106
|
+
@parameters.each do |para|
|
107
|
+
para.owner = self
|
108
|
+
end
|
109
|
+
self
|
110
|
+
end
|
111
|
+
|
112
|
+
def constructor?
|
113
|
+
!@return_type
|
114
|
+
end
|
115
|
+
|
116
|
+
def attribute?
|
117
|
+
false
|
118
|
+
end
|
119
|
+
|
120
|
+
def pretty_print(pp)
|
121
|
+
if cname
|
122
|
+
pp.text "#{signature} --> #{cname}"
|
123
|
+
else
|
124
|
+
pp.text signature
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|