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,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
|
data/lib/rbind/logger.rb
ADDED
data/lib/rbind/rbind.rb
ADDED
@@ -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 %>)
|