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.
Files changed (48) hide show
  1. data/lib/rbind.rb +5 -0
  2. data/lib/rbind/.default_parser.rb.swp +0 -0
  3. data/lib/rbind/.generator_c.rb.swp +0 -0
  4. data/lib/rbind/core.rb +13 -0
  5. data/lib/rbind/core/.rbase.rb.swp +0 -0
  6. data/lib/rbind/core/.rclass.rb.swp +0 -0
  7. data/lib/rbind/core/.rdata_type.rb.swp +0 -0
  8. data/lib/rbind/core/.roperation.rb.swp +0 -0
  9. data/lib/rbind/core/rattribute.rb +45 -0
  10. data/lib/rbind/core/rbase.rb +172 -0
  11. data/lib/rbind/core/rclass.rb +149 -0
  12. data/lib/rbind/core/rconst.rb +35 -0
  13. data/lib/rbind/core/rdata_type.rb +93 -0
  14. data/lib/rbind/core/renum.rb +5 -0
  15. data/lib/rbind/core/rgetter.rb +19 -0
  16. data/lib/rbind/core/rnamespace.rb +305 -0
  17. data/lib/rbind/core/roperation.rb +128 -0
  18. data/lib/rbind/core/rparameter.rb +40 -0
  19. data/lib/rbind/core/rsetter.rb +20 -0
  20. data/lib/rbind/core/rstruct.rb +87 -0
  21. data/lib/rbind/default_parser.rb +253 -0
  22. data/lib/rbind/generator_c.rb +352 -0
  23. data/lib/rbind/generator_ruby.rb +357 -0
  24. data/lib/rbind/logger.rb +13 -0
  25. data/lib/rbind/rbind.rb +68 -0
  26. data/lib/rbind/templates/c/CMakeLists.txt +11 -0
  27. data/lib/rbind/templates/c/consts.h +5 -0
  28. data/lib/rbind/templates/c/conversions.cc +4 -0
  29. data/lib/rbind/templates/c/conversions.hpp +10 -0
  30. data/lib/rbind/templates/c/find_package.txt +5 -0
  31. data/lib/rbind/templates/c/operation_wrapper.cc +15 -0
  32. data/lib/rbind/templates/c/operations.cc +23 -0
  33. data/lib/rbind/templates/c/operations.h +20 -0
  34. data/lib/rbind/templates/c/type_conversion.cc +45 -0
  35. data/lib/rbind/templates/c/type_conversion.hpp +5 -0
  36. data/lib/rbind/templates/c/type_delete.h +14 -0
  37. data/lib/rbind/templates/c/type_typedef.h +2 -0
  38. data/lib/rbind/templates/c/type_wrapper.h +12 -0
  39. data/lib/rbind/templates/c/types.cc +6 -0
  40. data/lib/rbind/templates/c/types.h +17 -0
  41. data/lib/rbind/templates/ruby/rbind.rb +44 -0
  42. data/lib/rbind/templates/ruby/rmethod.rb +12 -0
  43. data/lib/rbind/templates/ruby/rnamespace.rb +7 -0
  44. data/lib/rbind/templates/ruby/rstatic_method.rb +5 -0
  45. data/lib/rbind/templates/ruby/rtype.rb +77 -0
  46. data/lib/rbind/templates/ruby/rtype_constructor.rb +4 -0
  47. data/rbind.gemspec +17 -0
  48. metadata +101 -0
@@ -0,0 +1,357 @@
1
+ require 'fileutils'
2
+ require 'delegate'
3
+ require 'erb'
4
+
5
+ module Rbind
6
+ class GeneratorRuby
7
+ def self.keyword?(name)
8
+ %w{__FILE__ __LINE__ alias and begin BEGIN break case class def defined? do else elsif end END ensure false for if in module next nil not or redo rescue retry return self super then true undef unless until when while yield}.include? name
9
+ end
10
+
11
+ def self.normalize_arg_name(name)
12
+ name = name.to_s.sub(/\A#{RBase.cprefix}?/, "").gsub(/(?<!\A)\p{Lu}/u, '_\0').downcase
13
+ name = if keyword?(name)
14
+ "#{name}_"
15
+ else
16
+ name
17
+ end
18
+ # check for digits at the beginning
19
+ if name =~/\d(.*)/
20
+ "_#{name}"
21
+ else
22
+ name
23
+ end
24
+ end
25
+
26
+ def self.normalize_default_value(parameter)
27
+ return nil unless parameter.default_value
28
+ val = if parameter.type.basic_type? || parameter.type.ptr?
29
+ if parameter.type.name == "float"
30
+ parameter.default_value.gsub("f","")
31
+ elsif parameter.type.name == "double"
32
+ parameter.default_value.gsub(/\.$/,".0")
33
+ else
34
+ parameter.default_value
35
+ end
36
+ else
37
+ if(parameter.default_value =~ /(\w*)\((.*)\)/)
38
+ t = parameter.owner.owner.type($1,false)
39
+ if t
40
+ "#{normalize_type_name(t.full_name)}.new(#{$2})"
41
+ else
42
+ ns = RBase.namespace($1)
43
+ t = parameter.owner.owner.type(ns,false) if ns
44
+ ops = Array(t.operation($1,false)) if t
45
+ "#{normalize_method_name(ops.first.full_name)}(#{$2})" if ops && !ops.empy?
46
+ end
47
+ else
48
+ parameter.default_value
49
+ end
50
+ end
51
+ if val
52
+ val
53
+ else
54
+ raise "cannot parse default parameter value #{parameter.default_value} for #{parameter.owner.signature}"
55
+ end
56
+ end
57
+
58
+
59
+ def self.normalize_type_name(name)
60
+ name.split("::").map do |n|
61
+ n.gsub(/^(\w)(.*)/) do
62
+ $1.upcase+$2
63
+ end
64
+ end.join("::")
65
+ end
66
+
67
+ def self.normalize_basic_type_name(name)
68
+ @@basic_type_map ||= {"char *" => "string","unsigned char" => "uchar" ,"const char *" => "string" }
69
+ n = @@basic_type_map[name]
70
+ n ||= name
71
+ if n =~ /\*/
72
+ "pointer"
73
+ else
74
+ n
75
+ end
76
+ end
77
+
78
+ def self.normalize_method_name(name)
79
+ name = name.to_s.sub(/\A#{RBase.cprefix}?/, "").gsub(/(?<!\A)\p{Lu}/u, '_\0').downcase
80
+ str = ""
81
+ name.split("_").each_with_index do |n,i|
82
+ if n.empty?
83
+ str += "_"
84
+ next
85
+ end
86
+ if n.size == 1 && i > 1
87
+ str += n
88
+ else
89
+ str += "_#{n}"
90
+ end
91
+ end
92
+ name = str[1,str.size-1]
93
+ name = if name =~/^operator(.*)/
94
+ n = $1
95
+ if n =~ /\(\)/
96
+ raise "forbbiden method name #{name}"
97
+ elsif n=~ /(.*)(\d)/
98
+ if $1 == "[]"
99
+ "array_operator#{$2}"
100
+ elsif $1 == "+"
101
+ "plus_operator#{$2}"
102
+ elsif $1 == "-"
103
+ "minus_operator#{$2}"
104
+ elsif $1 == "*"
105
+ "mul_operator#{$2}"
106
+ elsif $1 == "/"
107
+ "div_operator#{$2}"
108
+ else
109
+ raise "forbbiden method name #{name}"
110
+ end
111
+ else
112
+ n
113
+ end
114
+ else
115
+ name
116
+ end
117
+ end
118
+
119
+ class HelperBase
120
+ attr_accessor :name
121
+ def initialize(name,root)
122
+ @name = name.to_s
123
+ @root = root
124
+ end
125
+
126
+ def full_name
127
+ @root.full_name
128
+ end
129
+
130
+ def binding
131
+ Kernel.binding
132
+ end
133
+ end
134
+
135
+ class RBindHelper < HelperBase
136
+ #TODO
137
+ attr_accessor :library_name
138
+
139
+ def initialize(name, root)
140
+ super
141
+ end
142
+
143
+ def normalize_t(name)
144
+ GeneratorRuby.normalize_type_name name
145
+ end
146
+
147
+ def normalize_bt(name)
148
+ GeneratorRuby.normalize_basic_type_name name
149
+ end
150
+
151
+ def normalize_m(name)
152
+ GeneratorRuby.normalize_method_name name
153
+ end
154
+
155
+ def add_accessors
156
+ str = ""
157
+ @root.each_type do |t|
158
+ next if t.basic_type? && !t.is_a?(RNamespace)
159
+ str += "\n#methods for #{t.full_name}\n"
160
+ if t.cdelete_method
161
+ str += "attach_function :#{normalize_m t.cdelete_method},"\
162
+ ":#{t.cdelete_method},[#{normalize_t t.full_name}],:void\n"
163
+ str += "attach_function :#{normalize_m t.cdelete_method}_struct,"\
164
+ ":#{t.cdelete_method},[#{normalize_t t.full_name}Struct],:void\n"
165
+ end
166
+ str += t.operations.map do |ops|
167
+ ops.map do |op|
168
+ return_type = if op.constructor?
169
+ "#{normalize_t op.owner.full_name}"
170
+ else
171
+ if op.return_type.basic_type?
172
+ ":#{normalize_bt op.return_type.csignature}"
173
+ else
174
+ "#{normalize_t op.return_type.full_name}"
175
+ end
176
+ end
177
+ args = op.cparameters.map do |p|
178
+ if p.type.basic_type?
179
+ ":#{normalize_bt p.type.csignature}"
180
+ else
181
+ "#{normalize_t p.type.full_name}"
182
+ end
183
+ end
184
+ fct_name = normalize_m op.cname
185
+ "attach_function :#{fct_name},:#{op.cname},[#{args.join(",")}],#{return_type}\n"
186
+ end.join
187
+ end.join
188
+ str+"\n"
189
+ end
190
+ str+"\n"
191
+ str.gsub(/\n/,"\n ")
192
+ end
193
+ end
194
+
195
+ class RTypeHelper < HelperBase
196
+ class OperationHelper < SimpleDelegator
197
+ def wrap_parameters_signature
198
+ parameters.map do |p|
199
+ n = GeneratorRuby.normalize_arg_name p.name
200
+ if p.default_value
201
+ "#{n} = #{GeneratorRuby.normalize_default_value p}"
202
+ else
203
+ n
204
+ end
205
+ end.join(", ")
206
+ rescue RuntimeError
207
+ ::Rbind.log.warn "ignoring all default parameter values for #{full_name} because of missing definitions."
208
+ parameters.map do |p|
209
+ GeneratorRuby.normalize_arg_name p.name
210
+ end.join(", ")
211
+ end
212
+
213
+ def wrap_parameters_call
214
+ paras = []
215
+ paras << "self" if instance_method?
216
+ paras += parameters.map do |p|
217
+ GeneratorRuby.normalize_arg_name p.name
218
+ end
219
+ paras.join(", ")
220
+ end
221
+
222
+ def name
223
+ if attribute?
224
+ name = GeneratorRuby.normalize_method_name(attribute.name)
225
+ if __getobj__.is_a? RGetter
226
+ name
227
+ else
228
+ "#{name}="
229
+ end
230
+ else
231
+ GeneratorRuby.normalize_method_name(__getobj__.alias || __getobj__.name)
232
+ end
233
+ end
234
+
235
+ def cname
236
+ GeneratorRuby.normalize_method_name(__getobj__.cname)
237
+ end
238
+
239
+ def binding
240
+ Kernel.binding
241
+ end
242
+ end
243
+
244
+ def initialize(name, root)
245
+ @type_wrapper = ERB.new(File.open(File.join(File.dirname(__FILE__),"templates","ruby","rtype.rb")).read,nil,"-")
246
+ @type_constructor_wrapper = ERB.new(File.open(File.join(File.dirname(__FILE__),"templates","ruby","rtype_constructor.rb")).read,nil,"-")
247
+ @namespace_wrapper = ERB.new(File.open(File.join(File.dirname(__FILE__),"templates","ruby","rnamespace.rb")).read,nil,"-")
248
+ @static_method_wrapper = ERB.new(File.open(File.join(File.dirname(__FILE__),"templates","ruby","rstatic_method.rb")).read)
249
+ @method_wrapper = ERB.new(File.open(File.join(File.dirname(__FILE__),"templates","ruby","rmethod.rb")).read,nil,'-')
250
+ super
251
+ end
252
+
253
+ def name
254
+ GeneratorRuby.normalize_type_name(@name)
255
+ end
256
+
257
+ def cname
258
+ GeneratorRuby.normalize_type_name(@root.cname)
259
+ end
260
+
261
+ def cdelete_method
262
+ GeneratorRuby.normalize_method_name(@root.cdelete_method)
263
+ end
264
+
265
+ def add_specializing
266
+ if @root.respond_to?(:specialize_ruby)
267
+ @root.specialize_ruby
268
+ else
269
+ nil
270
+ end
271
+ end
272
+
273
+ def add_constructor
274
+ raise "there is no constructor for namespaces!" if self.is_a?(RNamespace)
275
+ ops = Array(@root.operation(@root.name,false))
276
+ return until ops
277
+ ops.map do |c|
278
+ ch = OperationHelper.new(c)
279
+ @type_constructor_wrapper.result(ch.binding)
280
+ end.join("\n")
281
+ end
282
+
283
+ def add_consts
284
+ @root.consts.map do |c|
285
+ " #{c.name} = #{c.value}\n"
286
+ end.join
287
+ end
288
+
289
+ def add_methods
290
+ str = ""
291
+ @root.operations.each do |ops|
292
+ ops.each do |op|
293
+ next if op.constructor?
294
+ oph = OperationHelper.new(op)
295
+ str += if op.instance_method?
296
+ @method_wrapper.result(oph.binding)
297
+ else
298
+ @static_method_wrapper.result(oph.binding)
299
+ end
300
+ end
301
+ end
302
+ str
303
+ end
304
+
305
+ def add_types
306
+ str = ""
307
+ @root.each_type(false) do |t|
308
+ next if t.basic_type? && !t.is_a?(RNamespace)
309
+ t = RTypeHelper.new(t.name,t)
310
+ str += t.result
311
+ end
312
+ str
313
+ end
314
+
315
+ def full_name
316
+ @root.full_name
317
+ end
318
+
319
+ def result
320
+ str = if @root.is_a? RStruct
321
+ @type_wrapper.result(self.binding)
322
+ else
323
+ @namespace_wrapper.result(self.binding)
324
+ end
325
+ if(@root.root?)
326
+ str
327
+ else
328
+ str.gsub!("\n","\n ").gsub!(" \n","\n")
329
+ " "+str[0,str.size-4]
330
+ end
331
+ end
332
+ end
333
+
334
+ attr_accessor :module_name
335
+ attr_accessor :library_name
336
+
337
+
338
+ def initialize(root,module_name ="Rbind",library_name="rbind_lib")
339
+ @root = root
340
+ @rbind_wrapper = ERB.new(File.open(File.join(File.dirname(__FILE__),"templates","ruby","rbind.rb")).read)
341
+ @module_name = module_name
342
+ @library_name = library_name
343
+ end
344
+
345
+ def generate(path=nil)
346
+ FileUtils.mkdir_p(path) if path && !File.directory?(path)
347
+ file_rbind = File.new(File.join(path,"opencv.rb"),"w")
348
+ file_types = File.new(File.join(path,"opencv_types.rb"),"w")
349
+
350
+ types = RTypeHelper.new(@module_name,@root)
351
+ file_types.write types.result
352
+ rbind = RBindHelper.new(@module_name,@root)
353
+ rbind.library_name = @library_name
354
+ file_rbind.write @rbind_wrapper.result(rbind.binding)
355
+ end
356
+ end
357
+ end
@@ -0,0 +1,13 @@
1
+ require 'logger'
2
+
3
+ module Rbind
4
+ module Logger
5
+ attr_accessor :log
6
+ def self.extend_object(o)
7
+ super
8
+ o.log = ::Logger.new(STDOUT)
9
+ o.log.progname = o.name
10
+ end
11
+ end
12
+ extend ::Rbind::Logger
13
+ end
@@ -0,0 +1,68 @@
1
+ module Rbind
2
+ class Rbind
3
+ attr_accessor :parser
4
+ attr_accessor :generator_c
5
+ attr_accessor :generator_ruby
6
+ attr_accessor :includes
7
+ attr_accessor :name
8
+ attr_accessor :pkg_config
9
+
10
+ def initialize(name)
11
+ @name = name
12
+ @includes = []
13
+ @pkg_config = []
14
+ @parser = DefaultParser.new
15
+ lib_name = "rbind_#{name.downcase}"
16
+ @generator_c = GeneratorC.new(@parser,lib_name)
17
+ @generator_ruby = GeneratorRuby.new(@parser,name,lib_name)
18
+ end
19
+
20
+ def parse(*files)
21
+ files.each do |path|
22
+ parser.parse File.new(path).read
23
+ end
24
+ end
25
+
26
+ def generate(c_path = "src",ruby_path = "ruby/lib/#{name.downcase}")
27
+ generate_c c_path
28
+ generate_ruby ruby_path
29
+ end
30
+
31
+ def generate_ruby(path)
32
+ @generator_ruby.generate(path)
33
+ end
34
+
35
+ def generate_c(path)
36
+ @generator_c.includes = includes
37
+ @generator_c.pkg_config = pkg_config
38
+ @generator_c.generate(path)
39
+ end
40
+
41
+ def use_namespace(name)
42
+ t = if name.is_a? String
43
+ parser.type(name)
44
+ else
45
+ name
46
+ end
47
+ parser.use_namespace t
48
+ end
49
+
50
+ def type(*args)
51
+ parser.type(*args)
52
+ end
53
+
54
+ def on_type_not_found(&block)
55
+ @parser.on_type_not_found(&block)
56
+ end
57
+
58
+ def method_missing(m,*args)
59
+ t = @parser.type(m.to_s,false)
60
+ return t if t
61
+
62
+ op = @parser.operation(m.to_s,false)
63
+ return op if op
64
+
65
+ super
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,11 @@
1
+ cmake_minimum_required(VERSION 2.6)
2
+
3
+ PROJECT(<%= library_name %> CXX)
4
+
5
+ include(FindPkgConfig)
6
+ <%= find_packages %>
7
+
8
+ SET(RBIND_SRC types.cc operations.cc conversions.cc)
9
+ ADD_LIBRARY(<%= library_name %> SHARED ${RBIND_SRC})
10
+
11
+ TARGET_LINK_LIBRARIES(<%= library_name %> <%= libs %>)