rbind 0.0.22 → 0.0.23
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.
- checksums.yaml +4 -4
- data/do_install.sh +1 -0
- data/lib/rbind/clang/clang.rb +4 -0
- data/lib/rbind/clang/clang_types.rb +12 -1
- data/lib/rbind/clang_parser.rb +148 -76
- data/lib/rbind/core.rb +1 -0
- data/lib/rbind/core/rbase.rb +5 -13
- data/lib/rbind/core/rclass.rb +1 -1
- data/lib/rbind/core/rdata_type.rb +1 -1
- data/lib/rbind/core/renum.rb +1 -1
- data/lib/rbind/core/rnamespace.rb +59 -9
- data/lib/rbind/core/roperation.rb +3 -0
- data/lib/rbind/core/rtemplate_class.rb +62 -0
- data/lib/rbind/core/rtype_qualifier.rb +9 -0
- data/lib/rbind/default_parser.rb +16 -4
- data/lib/rbind/generator_c.rb +8 -0
- data/lib/rbind/generator_ruby.rb +134 -48
- data/lib/rbind/rbind.rb +21 -2
- data/lib/rbind/templates/c/operation_wrapper.cc +4 -4
- data/lib/rbind/templates/c/type_conversion.cc +7 -1
- data/lib/rbind/templates/c/type_conversion.hpp +1 -0
- data/lib/rbind/templates/ruby/rbind.rb +4 -0
- data/lib/rbind/templates/ruby/rmethod.rb +1 -1
- data/lib/rbind/templates/ruby/rnamespace.rb +2 -2
- data/lib/rbind/templates/ruby/roverloaded_method_call.rb +1 -1
- data/lib/rbind/templates/ruby/roverloaded_static_method.rb +1 -1
- data/lib/rbind/templates/ruby/rstatic_method.rb +1 -1
- data/lib/rbind/templates/ruby/rtype_constructor.rb +1 -1
- data/lib/rbind/templates/ruby/rtype_template.rb +1 -1
- data/lib/rbind/types/std_map.rb +29 -0
- data/rbind.gemspec +1 -1
- data/test/headers/non_public_classes.hpp +35 -0
- data/test/test_clang_parser.rb +52 -18
- metadata +5 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a49ac912bcaf33b590650a1a9764e4055e1324f6
|
4
|
+
data.tar.gz: 2711d7f9cfbbf28b32aa7765914971f9f07f1da6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2b5964e2a7e3b260879ded95cd659af9c918c16d78e7cd729ad34c720571d68a1eccdc620883ab8d246ef84dce2cea10ccb86eced4d7ee918bc42385967cb3f2
|
7
|
+
data.tar.gz: 8e855c1b6e0599cc5b9a966a794fe2badbdc4d7ba4ba1069d1b13560869c3c67319449ba5264a553014145ca46ec56fdd1b890c4b5ba6557e43aca00ff556086
|
data/do_install.sh
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
gem build rbind.gemspec; gem install --no-rdoc --no-ri rbind-0.0.21.gem
|
data/lib/rbind/clang/clang.rb
CHANGED
@@ -5,6 +5,10 @@ module::Clang
|
|
5
5
|
module Rbind
|
6
6
|
extend FFI::Library
|
7
7
|
clang_names = ['clang']
|
8
|
+
|
9
|
+
clang_names = Dir.glob("/usr/lib/libclang*")
|
10
|
+
clang_names.flatten!
|
11
|
+
|
8
12
|
%w{3.4 3.3 3.2}.each do |llvm_version|
|
9
13
|
clang_names << File.join("/", "usr", "lib", "llvm-#{llvm_version}", "lib", "libclang.so")
|
10
14
|
end
|
@@ -85,6 +85,8 @@ module Clang
|
|
85
85
|
# extend Structs to support auto dispose
|
86
86
|
module Rbind
|
87
87
|
class Cursor < FFI::Struct
|
88
|
+
extend ::Rbind::Logger
|
89
|
+
|
88
90
|
def null?
|
89
91
|
1 == Rbind::cursor_is_null(self)
|
90
92
|
end
|
@@ -149,13 +151,22 @@ module Clang
|
|
149
151
|
while !cursor.translation_unit?
|
150
152
|
namespace << cursor.spelling
|
151
153
|
cursor = cursor.semantic_parent
|
154
|
+
if cursor.invalid_file?
|
155
|
+
Cursor.log.warn "Cursor #{self} with invalid file"
|
156
|
+
break
|
157
|
+
end
|
152
158
|
end
|
159
|
+
namespace = namespace.select{|s| !s.empty?}
|
153
160
|
namespace.reverse.join("::")
|
154
161
|
end
|
155
162
|
|
156
163
|
def translation_unit?
|
157
164
|
kind == :translation_unit
|
158
165
|
end
|
166
|
+
|
167
|
+
def invalid_file?
|
168
|
+
kind == :invalid_file
|
169
|
+
end
|
159
170
|
|
160
171
|
def expression
|
161
172
|
num = FFI::MemoryPointer.new(:uint,1)
|
@@ -198,7 +209,7 @@ module Clang
|
|
198
209
|
Rbind::get_cursor_type self
|
199
210
|
end
|
200
211
|
|
201
|
-
def
|
212
|
+
def virtual_base?
|
202
213
|
1 == Rbind::is_virtual_base(self)
|
203
214
|
end
|
204
215
|
|
data/lib/rbind/clang_parser.rb
CHANGED
@@ -40,13 +40,28 @@ module Rbind
|
|
40
40
|
include Hooks
|
41
41
|
extend ::Rbind::Logger
|
42
42
|
|
43
|
+
def self.default_arguments
|
44
|
+
@default_arguments || ["-xc++","-fno-rtti"]
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.default_arguments=(args)
|
48
|
+
if not args.kind_of?(Array)
|
49
|
+
raise ArgumentError, "Clang::default_arguments require Array"
|
50
|
+
end
|
51
|
+
@default_arguments = args
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.reset_default_arguments
|
55
|
+
@default_arguments = []
|
56
|
+
end
|
57
|
+
|
43
58
|
def initialize(root=nil)
|
44
59
|
super(nil,root)
|
45
60
|
add_default_types if !root
|
46
61
|
@clang = Clang::Clang.new
|
47
62
|
end
|
48
63
|
|
49
|
-
def parse(file_path,args =
|
64
|
+
def parse(file_path, args = ClangParser.default_arguments)
|
50
65
|
tu = @clang.translation_unit(file_path,args)
|
51
66
|
process(tu.cursor)
|
52
67
|
self
|
@@ -78,7 +93,8 @@ module Rbind
|
|
78
93
|
end
|
79
94
|
|
80
95
|
# if rbind_type is given only pointer/ref or qualifier are applied
|
81
|
-
def to_rbind_type(parent,cursor,rbind_type=nil,type_getter = :type,canonical = true)
|
96
|
+
def to_rbind_type(parent,cursor,rbind_type=nil,type_getter = :type,canonical = true, use_fallback = true)
|
97
|
+
ClangParser.log.debug "Parent: #{parent} --> cursor: #{cursor.expression}, spelling #{cursor.spelling}"
|
82
98
|
clang_type = cursor.send(type_getter)
|
83
99
|
return nil if clang_type.null?
|
84
100
|
clang_type = clang_type.canonical_type if canonical
|
@@ -110,8 +126,13 @@ module Rbind
|
|
110
126
|
end
|
111
127
|
t = parent.type(name,!canonical)
|
112
128
|
end
|
113
|
-
|
114
|
-
|
129
|
+
|
130
|
+
# try again without canonical when type could not be found or type is template
|
131
|
+
if use_fallback
|
132
|
+
if !t || t.template?
|
133
|
+
return to_rbind_type(parent,cursor,rbind_type,type_getter,false, false)
|
134
|
+
end
|
135
|
+
end
|
115
136
|
|
116
137
|
# add pointer level
|
117
138
|
1.upto(level) do
|
@@ -133,74 +154,85 @@ module Rbind
|
|
133
154
|
end
|
134
155
|
|
135
156
|
# entry call to parse a file
|
136
|
-
def process(cursor,parent = self)
|
137
|
-
access = :public
|
157
|
+
def process(cursor, parent = self, access = :public)
|
138
158
|
last_obj = nil
|
139
159
|
cursor.visit_children(false) do |cu,cu_parent|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
process_class(cu,parent)
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
access
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
last_obj
|
160
|
+
ClangParser.log.debug "process ----->#{cu.kind} #{cu.spelling} #{cu.type.kind} #{cu.specialized_template.kind} ---> expr: #{cu.expression.join('|')} -- public: #{cu.public?} access: #{access}"
|
161
|
+
begin
|
162
|
+
last_obj = case cu.kind
|
163
|
+
when :namespace
|
164
|
+
process_namespace(cu,parent)
|
165
|
+
when :enum_decl
|
166
|
+
process_enum(cu,parent) if access == :public
|
167
|
+
when :union_decl
|
168
|
+
# puts "got union declaration #{cu.spelling}"
|
169
|
+
when :struct_decl
|
170
|
+
process_class(cu,parent,:public) if access == :public
|
171
|
+
when :class_decl
|
172
|
+
process_class(cu,parent, :private) if access == :public
|
173
|
+
when :function_decl
|
174
|
+
process_function(cu,parent) if access == :public
|
175
|
+
when :macro_expansion # CV_WRAP ...
|
176
|
+
# puts "got macro #{cu.spelling} #{cu.location}"
|
177
|
+
when :function_template
|
178
|
+
# puts "got template fuction #{cu.spelling} #{cu.location}"
|
179
|
+
when :class_template
|
180
|
+
process_class_template(cu,parent, access) if access == :public
|
181
|
+
when :template_type_parameter
|
182
|
+
if !cu.spelling.empty?
|
183
|
+
parent.add_type(RTemplateParameter.new(cu.spelling))
|
184
|
+
else
|
185
|
+
ClangParser.log.info "no template parameter name"
|
186
|
+
end
|
187
|
+
when :x_access_specifier
|
188
|
+
access = normalize_accessor(cu.cxx_access_specifier)
|
189
|
+
when :x_base_specifier
|
190
|
+
if access == :public
|
191
|
+
next
|
192
|
+
end
|
193
|
+
local_access = normalize_accessor(cu.cxx_access_specifier)
|
194
|
+
klass_name = cu.spelling
|
195
|
+
if cu.spelling =~ /\s?([^\s]+$)/
|
196
|
+
klass_name = $1
|
197
|
+
end
|
198
|
+
ClangParser.log.info "auto add parent class #{klass_name} if needed"
|
199
|
+
p = parent.type(RClass.new(RBase.normalize(klass_name)), true)
|
200
|
+
parent.add_parent p,local_access
|
201
|
+
when :field_decl
|
202
|
+
process_field(cu,parent) if access == :public
|
203
|
+
when :constructor
|
204
|
+
if access == :public
|
205
|
+
f = process_function(cu,parent)
|
206
|
+
f.return_type = nil if f
|
207
|
+
f
|
208
|
+
end
|
209
|
+
when :x_method
|
210
|
+
process_function(cu,parent) if access == :public
|
211
|
+
when :typedef_decl
|
212
|
+
if access != :public
|
213
|
+
next
|
214
|
+
end
|
215
|
+
# rename object if parent has no name
|
216
|
+
if last_obj && last_obj.respond_to?(:name) && last_obj.name =~ /no_name/
|
217
|
+
ClangParser.log.info "rename #{last_obj.name} to #{cu.spelling}"
|
218
|
+
last_obj.rename(cu.spelling)
|
219
|
+
last_obj
|
220
|
+
else
|
221
|
+
process_typedef(cu, parent)
|
222
|
+
end
|
223
|
+
when :var_decl
|
224
|
+
process_variable(cu,parent) if access == :public
|
225
|
+
when :unexposed_decl
|
226
|
+
process(cu) if access == :public
|
227
|
+
else
|
228
|
+
#puts "skip: #{cu.spelling}"
|
197
229
|
end
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
230
|
+
rescue Exception => e
|
231
|
+
ClangParser.log.debug "Parsing failed -- skipping"
|
232
|
+
end
|
233
|
+
raise ClangParserError.new("jjj",cu) if last_obj.is_a? Fixnum
|
234
|
+
|
235
|
+
|
204
236
|
end
|
205
237
|
end
|
206
238
|
|
@@ -262,7 +294,7 @@ module Rbind
|
|
262
294
|
a
|
263
295
|
end
|
264
296
|
|
265
|
-
def process_class_template(cursor,parent)
|
297
|
+
def process_class_template(cursor,parent,access)
|
266
298
|
class_name = cursor.spelling
|
267
299
|
ClangParser.log.info "processing class template #{parent}::#{class_name}"
|
268
300
|
|
@@ -275,11 +307,11 @@ module Rbind
|
|
275
307
|
ClangParser.log.info " reopening existing class template #{klass}"
|
276
308
|
klass
|
277
309
|
end
|
278
|
-
process(cursor,klass)
|
310
|
+
process(cursor,klass, access)
|
279
311
|
klass
|
280
312
|
end
|
281
313
|
|
282
|
-
def process_class(cursor,parent)
|
314
|
+
def process_class(cursor,parent,access)
|
283
315
|
class_name = cursor.spelling
|
284
316
|
class_name = if class_name.empty?
|
285
317
|
"no_name_class"
|
@@ -306,13 +338,13 @@ module Rbind
|
|
306
338
|
ClangParser.log.info " skipping template #{name}"
|
307
339
|
nil
|
308
340
|
else
|
309
|
-
ClangParser.log.warn " skipping non empty
|
341
|
+
ClangParser.log.warn " skipping non empty class #{name}"
|
310
342
|
#raise "Cannot reopening existing class #{klass} which is non-empty!"
|
311
343
|
nil
|
312
344
|
end
|
313
345
|
end
|
314
346
|
#klass.extern_package_name = nil
|
315
|
-
process(cursor,klass) if klass
|
347
|
+
process(cursor,klass,access) if klass
|
316
348
|
klass
|
317
349
|
end
|
318
350
|
|
@@ -339,8 +371,10 @@ module Rbind
|
|
339
371
|
# to prevent name clashes
|
340
372
|
expression = cursor.expression.join()
|
341
373
|
args.each_with_index do |arg,idx|
|
342
|
-
if(!arg.default_value && (expression =~ /#{arg.name}
|
343
|
-
|
374
|
+
if(!arg.default_value && (expression =~ /#{arg.name}(=\w*)?[,)]/))
|
375
|
+
if $1 and !$1.empty?
|
376
|
+
arg.default_value = $1.sub("=","")
|
377
|
+
end
|
344
378
|
end
|
345
379
|
arg.name = if(arg.name == "no_name_arg")
|
346
380
|
arg.name + idx.to_s
|
@@ -368,6 +402,7 @@ module Rbind
|
|
368
402
|
|
369
403
|
# type_getter is also used for :result_type
|
370
404
|
def process_parameter(cursor,parent,type_getter = :type)
|
405
|
+
ClangParser.log.debug "process_parameter: spelling: '#{cursor.spelling}' type: '#{cursor.type}' kind '#{cursor.type.kind} parent #{parent}"
|
371
406
|
para_name = cursor.spelling
|
372
407
|
para_name = if para_name.empty?
|
373
408
|
"no_name_arg"
|
@@ -380,6 +415,7 @@ module Rbind
|
|
380
415
|
name_space = []
|
381
416
|
|
382
417
|
cursor.visit_children do |cu,_|
|
418
|
+
ClangParser.log.info "process parameter: cursor kind: #{cu.kind} #{cu.expression}"
|
383
419
|
case cu.kind
|
384
420
|
when :integer_literal
|
385
421
|
exp = cu.expression
|
@@ -412,6 +448,14 @@ module Rbind
|
|
412
448
|
name_space << cu.spelling
|
413
449
|
when :type_ref
|
414
450
|
type_cursor = cu
|
451
|
+
when :compound_stmt
|
452
|
+
when :parm_decl
|
453
|
+
when :member_ref
|
454
|
+
when :constant_array
|
455
|
+
exp = cu.expression
|
456
|
+
exp.pop
|
457
|
+
default_value = exp.gsub("{","[")
|
458
|
+
default_value = default_value.gsub("}","]")
|
415
459
|
end
|
416
460
|
end
|
417
461
|
type = if template_name.empty?
|
@@ -447,5 +491,33 @@ module Rbind
|
|
447
491
|
rescue RuntimeError => e
|
448
492
|
raise ClangParserError.new(e.to_s,cursor)
|
449
493
|
end
|
494
|
+
|
495
|
+
def process_typedef(cu, parent)
|
496
|
+
ClangParser.log.debug "process_typedef: #{cu}: expression: #{cu.expression} parent: #{parent}"
|
497
|
+
exp = cu.expression.join(" ")
|
498
|
+
|
499
|
+
# Remove typedef label and extract orig type and alias
|
500
|
+
orig_and_alias = exp.sub("typedef","")
|
501
|
+
orig_and_alias = orig_and_alias.sub(";","").strip
|
502
|
+
orig_type = nil
|
503
|
+
alias_type = nil
|
504
|
+
|
505
|
+
if orig_and_alias =~ /(.*)\s+([^\s]+)/
|
506
|
+
orig_type = $1
|
507
|
+
alias_type = $2
|
508
|
+
else
|
509
|
+
raise RuntimeError,"Cannot parse typedef expression #{exp}"
|
510
|
+
end
|
511
|
+
|
512
|
+
begin
|
513
|
+
t = parent.type(orig_type)
|
514
|
+
ClangParser.log.debug "process_typedef: orig: '#{orig_type}' alias: #{alias_type}"
|
515
|
+
parent.add_type_alias(t, alias_type)
|
516
|
+
rescue RuntimeError => e
|
517
|
+
ClangParser.log.warn "Cannot process typedef expression for orig: '#{orig_type}' alias: '#{alias_type}' : #{e}"
|
518
|
+
end
|
519
|
+
parent
|
520
|
+
end
|
521
|
+
|
450
522
|
end
|
451
523
|
end
|
data/lib/rbind/core.rb
CHANGED
data/lib/rbind/core/rbase.rb
CHANGED
@@ -20,25 +20,17 @@ module Rbind
|
|
20
20
|
name = normalize(name)
|
21
21
|
cn = "#{cprefix}#{name.gsub("::","_")}"
|
22
22
|
if cn =~ /operator/
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
cn = cn.gsub("operator+=","operator_add")
|
28
|
-
cn = cn.gsub("operator-=","operator_sub")
|
29
|
-
cn = cn.gsub("operator+","operator_plus")
|
30
|
-
cn = cn.gsub("operator-","operator_minus")
|
31
|
-
cn = cn.gsub("operator*","operator_mult")
|
32
|
-
cn = cn.gsub("operator/","operator_div")
|
33
|
-
cn = cn.gsub("operator!","operator_not")
|
34
|
-
cn = cn.gsub("operator&","operator_and")
|
35
|
-
cn = cn.gsub("operator[]","operator_array")
|
23
|
+
# Use alias instead of operator symbol for name
|
24
|
+
RNamespace.default_operator_alias.each do |op, alias_name|
|
25
|
+
cn = cn.gsub("operator#{op}","operator_#{alias_name}")
|
26
|
+
end
|
36
27
|
end
|
37
28
|
cn = cn.gsub("*","_ptr")
|
38
29
|
cn = cn.gsub("&","_ref")
|
39
30
|
cn = cn.gsub("<","_")
|
40
31
|
cn = cn.gsub(">","")
|
41
32
|
cn = cn.gsub(",","__")
|
33
|
+
cn
|
42
34
|
end
|
43
35
|
|
44
36
|
def normalize(name)
|
data/lib/rbind/core/rclass.rb
CHANGED