rbind 0.0.16 → 0.0.17

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 (54) hide show
  1. data/lib/rbind.rb +1 -0
  2. data/lib/rbind/clang/clang.rb +3699 -0
  3. data/lib/rbind/clang/clang_types.rb +327 -0
  4. data/lib/rbind/clang_parser.rb +451 -0
  5. data/lib/rbind/core.rb +7 -4
  6. data/lib/rbind/core/rattribute.rb +17 -21
  7. data/lib/rbind/core/rbase.rb +98 -64
  8. data/lib/rbind/core/rcallback.rb +15 -0
  9. data/lib/rbind/core/rclass.rb +79 -16
  10. data/lib/rbind/core/rdata_type.rb +40 -39
  11. data/lib/rbind/core/renum.rb +18 -0
  12. data/lib/rbind/core/rnamespace.rb +189 -52
  13. data/lib/rbind/core/roperation.rb +52 -20
  14. data/lib/rbind/core/rparameter.rb +43 -8
  15. data/lib/rbind/core/rpointer.rb +70 -0
  16. data/lib/rbind/core/rreference.rb +54 -0
  17. data/lib/rbind/core/rtemplate_class.rb +49 -0
  18. data/lib/rbind/core/rtype_qualifier.rb +60 -0
  19. data/lib/rbind/default_parser.rb +48 -36
  20. data/lib/rbind/generator_c.rb +2 -2
  21. data/lib/rbind/generator_extern.rb +1 -3
  22. data/lib/rbind/generator_ruby.rb +201 -47
  23. data/lib/rbind/logger.rb +3 -0
  24. data/lib/rbind/rbind.rb +25 -9
  25. data/lib/rbind/templates/c/CMakeLists.txt +6 -6
  26. data/lib/rbind/templates/ruby/rbind.rb +1 -1
  27. data/lib/rbind/templates/ruby/rmethod.rb +4 -1
  28. data/lib/rbind/templates/ruby/rnamespace.rb +2 -1
  29. data/lib/rbind/templates/ruby/roverloaded_method.rb +3 -1
  30. data/lib/rbind/templates/ruby/roverloaded_method_call.rb +1 -0
  31. data/lib/rbind/templates/ruby/roverloaded_static_method.rb +3 -2
  32. data/lib/rbind/templates/ruby/rstatic_method.rb +4 -1
  33. data/lib/rbind/templates/ruby/rtype.rb +19 -16
  34. data/lib/rbind/templates/ruby/rtype_template.rb +7 -0
  35. data/lib/rbind/{core/rstring.rb → types/std_string.rb} +8 -8
  36. data/lib/rbind/types/std_vector.rb +100 -0
  37. data/rbind.gemspec +2 -2
  38. data/test/headers/cfunctions.h +7 -0
  39. data/test/headers/classes.hpp +29 -0
  40. data/test/headers/constants.hpp +14 -0
  41. data/test/headers/enums.hpp +22 -0
  42. data/test/headers/std_string.hpp +26 -0
  43. data/test/headers/std_vector.hpp +31 -0
  44. data/test/headers/structs.hpp +34 -0
  45. data/test/headers/templates.hpp +20 -0
  46. data/test/test_clang_parser.rb +146 -0
  47. data/test/test_generator_ruby.rb +0 -5
  48. data/test/test_roperation.rb +144 -0
  49. data/test/test_rparameter.rb +88 -0
  50. metadata +24 -7
  51. data/lib/rbind/core/.roperation.rb.swp +0 -0
  52. data/lib/rbind/core/rconst.rb +0 -35
  53. data/lib/rbind/core/rstruct.rb +0 -87
  54. data/lib/rbind/core/rvector.rb +0 -27
@@ -2,9 +2,9 @@ require 'open3'
2
2
 
3
3
  module Rbind
4
4
  class Rbind
5
- attr_accessor :parser
6
- attr_accessor :generator_c
7
- attr_accessor :generator_ruby
5
+ attr_reader :parser
6
+ attr_reader :generator_c
7
+ attr_reader :generator_ruby
8
8
  attr_accessor :includes
9
9
  attr_accessor :name
10
10
  attr_accessor :pkg_config
@@ -46,12 +46,12 @@ module Rbind
46
46
  end
47
47
  end
48
48
 
49
- def initialize(name)
49
+ def initialize(name,parser = DefaultParser.new)
50
50
  @name = name
51
51
  @includes = []
52
52
  @pkg_config = []
53
53
  @gems = []
54
- @parser = DefaultParser.new
54
+ @parser = parser
55
55
  lib_name = "rbind_#{name.downcase}"
56
56
  @generator_c = GeneratorC.new(@parser,lib_name)
57
57
  @generator_ruby = GeneratorRuby.new(@parser,name,lib_name)
@@ -87,20 +87,23 @@ module Rbind
87
87
 
88
88
  # parses other rbind packages
89
89
  def parse_extern
90
+ # extern package are always paresed with the default parser
91
+ local_parser = DefaultParser.new(parser)
90
92
  paths = Rbind.rbind_pkg_paths(@pkg_config)
91
93
  paths.each do |pkg|
92
94
  config = YAML.load(File.open(File.join(pkg,"config.rbind")).read)
93
95
  path = File.join(pkg,"extern.rbind")
94
96
  ::Rbind.log.info "parsing extern rbind pkg file #{path}"
95
- parser.parse(File.open(path).read,config.ruby_module_name)
97
+ local_parser.parse(File.open(path).read,config.ruby_module_name)
96
98
  end
97
99
  @gems.each do |gem|
98
100
  path = Rbind.gem_path(gem)
99
101
  config = YAML.load(File.open(File.join(path,"config.rbind")).read)
100
102
  path = File.join(path,"extern.rbind")
101
103
  ::Rbind.log.info "parsing extern gem file #{path}"
102
- parser.parse(File.open(path).read,config.ruby_module_name)
104
+ local_parser.parse(File.open(path).read,config.ruby_module_name)
103
105
  end
106
+ self
104
107
  end
105
108
 
106
109
  def parse_headers_dry(*headers)
@@ -191,9 +194,22 @@ module Rbind
191
194
  @generator_c.libs
192
195
  end
193
196
 
194
- def import_std_string
197
+ def add_std_string
195
198
  @generator_c.includes << "<string>"
196
- @parser.add_type(RString.new("std::string",@parser))
199
+ @parser.add_type(StdString.new("std::string",@parser))
200
+ @parser.type_alias["basic_string"] = @parser.std.string
201
+ self
202
+ end
203
+
204
+ def add_std_vector
205
+ @generator_c.includes << "<vector>"
206
+ @parser.add_type(StdVector.new("std::vector"))
207
+ self
208
+ end
209
+
210
+ def add_std_types
211
+ add_std_vector
212
+ add_std_string
197
213
  end
198
214
 
199
215
  def method_missing(m,*args)
@@ -18,13 +18,13 @@ TARGET_LINK_LIBRARIES(<%= library_name %> <%= libs %> ${GEM_LIBRARIES})
18
18
 
19
19
  configure_file(${CMAKE_CURRENT_SOURCE_DIR}/rbind.pc.in ${CMAKE_CURRENT_BINARY_DIR}/<%= library_name %>.pc @ONLY)
20
20
 
21
- set(ROOT_FOLDER ${CMAKE_CURRENT_SOURCE_DIR}/..)
21
+ set(ROOT_FOLDER ${CMAKE_CURRENT_SOURCE_DIR}/../..)
22
22
  if(GEM_INSTALL)
23
23
  # local install
24
- install(TARGETS <%= library_name %> LIBRARY DESTINATION ${ROOT_FOLDER}/lib/lib)
25
- install(FILES types.h operations.h conversions.hpp DESTINATION ${ROOT_FOLDER}/lib/include)
26
- install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/extern.rbind DESTINATION ${ROOT_FOLDER}/lib/include)
27
- install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/config.rbind DESTINATION ${ROOT_FOLDER}/lib/include)
24
+ install(TARGETS <%= library_name %> LIBRARY DESTINATION ${ROOT_FOLDER}/lib)
25
+ install(FILES types.h operations.h conversions.hpp DESTINATION ${ROOT_FOLDER}/include)
26
+ install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/extern.rbind DESTINATION ${ROOT_FOLDER}/include)
27
+ install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/config.rbind DESTINATION ${ROOT_FOLDER}/include)
28
28
  else()
29
29
  # global install
30
30
  install(FILES ${CMAKE_CURRENT_BINARY_DIR}/<%= library_name %>.pc DESTINATION lib/pkgconfig)
@@ -36,7 +36,7 @@ else()
36
36
  FIND_PACKAGE(Ruby)
37
37
  IF(NOT RUBY_INCLUDE_PATH)
38
38
  MESSAGE(STATUS "Ruby library not found. Cannot install ruby extensions")
39
- ELSEIF(NOT RUBY_EXTENSIONS_AVAILABLE)
39
+ ELSEIF(RUBY_EXTENSIONS_AVAILABLE)
40
40
  STRING(REGEX REPLACE ".*lib(32|64)?/?" "lib/" RUBY_LIBRARY_INSTALL_DIR ${RUBY_RUBY_LIB_PATH})
41
41
  INSTALL(DIRECTORY ${ROOT_FOLDER}/lib/ruby/ DESTINATION ${RUBY_LIBRARY_INSTALL_DIR}
42
42
  FILES_MATCHING PATTERN "*.rb")
@@ -8,7 +8,7 @@ module <%= name %>
8
8
  extend FFI::Library
9
9
 
10
10
  #load library <%= library_name %>
11
- path = File.join(File.dirname(__FILE__),"..","..","lib")
11
+ path = File.join(File.dirname(__FILE__),"..")
12
12
  path = if Dir.exist?(path)
13
13
  Dir.chdir(path) do
14
14
  path = Dir.glob("lib<%= library_name %>.*").first
@@ -1,5 +1,7 @@
1
- # wrapper for <%= signature %>
1
+ <%= add_doc -%>
2
+ # @note wrapper for <%= signature %>
2
3
  def <%=name%>(<%= wrap_parameters_signature %>)
4
+ <%= add_specialize_ruby -%>
3
5
  <%- if return_type.basic_type? || operator? -%>
4
6
  Rbind::<%= cname %>( <%= wrap_parameters_call %>)
5
7
  <%- else -%>
@@ -11,4 +13,5 @@
11
13
  result
12
14
  <%- end -%>
13
15
  end
16
+ <%= add_alias -%>
14
17
 
@@ -1,4 +1,5 @@
1
- # wrapper for <%= full_name %>
1
+ <%= add_doc -%>
2
+ # @note wrapper for <%= full_name %>
2
3
  module <%= name %>
3
4
  # @!group Constants
4
5
  <%= add_consts%>
@@ -1,6 +1,8 @@
1
- # wrapper for overloaded method <%= name %>
1
+ <%= add_doc -%>
2
+ # @note wrapper for overloaded method <%= name %>
2
3
  def <%=name%>(*args)
3
4
  <%= add_methods %>
4
5
  raise ArgumentError, "No overloaded signature fits to: #{args.map(&:class)}"
5
6
  end
7
+ <%= add_alias -%>
6
8
 
@@ -6,6 +6,7 @@
6
6
  targs[i] = @@<%=cname%>_defaults<%=index%>[i]
7
7
  end
8
8
  begin
9
+ <%= add_specialize_ruby -%>
9
10
  <%- if !return_type || return_type.basic_type? || operator? -%>
10
11
  <%- if constructor? || !instance_method? -%>
11
12
  return Rbind::<%= cname %>(*targs)
@@ -1,6 +1,7 @@
1
- # wrapper for overloaded method <%= name %>
1
+ <%= add_doc -%>
2
+ # @note wrapper for overloaded method <%= name %>
2
3
  def self.<%=name%>(*args)
3
4
  <%= add_methods %>
4
5
  raise ArgumentError, "No overloaded signature fits to: #{args.map(&:class)}"
5
6
  end
6
-
7
+ <%= add_alias -%>
@@ -1,5 +1,8 @@
1
- # wrapper for <%= signature %>
1
+ <%= add_doc -%>
2
+ # @note wrapper for <%= signature %>
2
3
  def self.<%= name %>(<%= wrap_parameters_signature %>)
4
+ <%= add_specialize_ruby -%>
3
5
  Rbind::<%= cname %>(<%= wrap_parameters_call %>)
4
6
  end
7
+ <%= add_alias -%>
5
8
 
@@ -1,5 +1,5 @@
1
- # @api private
2
- # object wrapping <%= full_name %>
1
+ # @private
2
+ # @note object wrapping <%= full_name %>
3
3
  class <%= name %>Struct < FFI::Struct
4
4
  layout :version,:uchar,
5
5
  :size,:size_t,
@@ -14,11 +14,12 @@ class <%= name %>Struct < FFI::Struct
14
14
  end
15
15
  end
16
16
 
17
+ <%= add_doc -%>
17
18
  class <%= name %>
18
19
  extend FFI::DataConverter
19
20
  native_type FFI::Type::POINTER
20
21
 
21
- # @api private
22
+ # @private
22
23
  #
23
24
  # Returns the *Struct type that Rbind uses to store additional information
24
25
  # about the memory used by this object
@@ -28,6 +29,7 @@ class <%= name %>
28
29
  <%= name %>Struct
29
30
  end
30
31
 
32
+ <%= add_constructor_doc -%>
31
33
  def self.new(*args)
32
34
  if args.first.is_a?(FFI::Pointer) || args.first.is_a?(<%= name %>Struct)
33
35
  raise ArgumentError, "too many arguments for creating #{self.name} from Pointer" unless args.size == 1
@@ -37,7 +39,7 @@ class <%= name %>
37
39
  raise ArgumentError, "no constructor for #{self}(#{args.inspect})"
38
40
  end
39
41
 
40
- # @api private
42
+ # @private
41
43
  def self.rbind_to_native(obj,context)
42
44
  if obj.is_a? <%= name %>
43
45
  obj.__obj_ptr__
@@ -46,14 +48,14 @@ class <%= name %>
46
48
  end
47
49
  end
48
50
 
49
- # @api private
51
+ # @private
50
52
  def self.rbind_from_native(ptr,context)
51
53
  <%= name %>.new(ptr)
52
54
  end
53
55
 
54
- # @api private
56
+ # @private
55
57
  #
56
- # Performs the convertion a Ruby representation into the FFI representation
58
+ # Performs the conversion a Ruby representation into the FFI representation
57
59
  #
58
60
  # @param [Object] obj the Ruby representation
59
61
  # @param context necessary but undocumented argument from FFI
@@ -62,9 +64,9 @@ class <%= name %>
62
64
  rbind_to_native(obj,context)
63
65
  end
64
66
 
65
- # @api private
67
+ # @private
66
68
  #
67
- # Performs the convertion from FFI into the Ruby representation that
69
+ # Performs the conversion from FFI into the Ruby representation that
68
70
  # corresponds to this type
69
71
  #
70
72
  # @param [FFI::Pointer,FFI::AutoPointer] ptr
@@ -74,10 +76,10 @@ class <%= name %>
74
76
  rbind_from_native(ptr,context)
75
77
  end
76
78
 
77
- # @api private
79
+ # @private
78
80
  attr_reader :__obj_ptr__
79
81
 
80
- # @api private
82
+ # @private
81
83
  def initialize(ptr)
82
84
  @__obj_ptr__ = if ptr.is_a? <%= name %>Struct
83
85
  ptr
@@ -86,7 +88,7 @@ class <%= name %>
86
88
  end
87
89
  end
88
90
 
89
- # @api private
91
+ # @private
90
92
  # returns true if the underlying pointer is owner of
91
93
  # the real object
92
94
  def __owner__?
@@ -98,10 +100,6 @@ class <%= name %>
98
100
  <%= add_to_s %>
99
101
  end
100
102
 
101
- # @!group Sepcializing
102
- <%= add_specializing %>
103
- # @!endgroup
104
-
105
103
  # @!group Constants
106
104
  <%= add_consts %>
107
105
  # @!endgroup
@@ -109,7 +107,12 @@ class <%= name %>
109
107
  # methods
110
108
  <%= add_methods %>
111
109
 
110
+ # @!group Specializing
111
+ <%= add_specializing %>
112
+ # @!endgroup
113
+
112
114
  # types
113
115
  <%= add_types %>
116
+
114
117
  end
115
118
 
@@ -0,0 +1,7 @@
1
+ # template <%= full_name %>
2
+ class <%= name %>
3
+ # @!group Sepcializing
4
+ <%= add_specializing %>
5
+ # @!endgroup
6
+ end
7
+
@@ -1,30 +1,29 @@
1
1
  module Rbind
2
- class RString < RClass
2
+ class StdString < RClass
3
3
  def initialize(name,root)
4
4
  super(name)
5
5
 
6
6
  size_t = root.type("size_t")
7
7
  char = root.type("char")
8
8
  string = root.type("c_string")
9
- const_string = root.type("const_c_string")
9
+ const_string = string.to_const
10
10
  bool = root.type("bool")
11
11
  void = root.type("void")
12
12
  int = root.type("int")
13
13
 
14
14
  add_operation ROperation.new(self.name,nil)
15
- add_operation ROperation.new(self.name,nil,RParameter.new("other",self))
16
- add_operation ROperation.new(self.name,nil,RParameter.new("str",string),RParameter.new("size",size_t))
15
+ add_operation ROperation.new(self.name,nil,RParameter.new("other",self).to_const)
16
+ add_operation ROperation.new(self.name,nil,RParameter.new("str",string).to_const,RParameter.new("size",size_t))
17
17
  add_operation ROperation.new("size",size_t)
18
18
  add_operation ROperation.new("length",size_t)
19
19
  add_operation ROperation.new("operator[]",char,RParameter.new("idx",size_t))
20
20
  add_operation ROperation.new("c_str",const_string)
21
21
  add_operation ROperation.new("empty",bool)
22
22
  add_operation ROperation.new("clear",void)
23
- add_operation ROperation.new("compare",int,RParameter.new("other",self))
24
- add_operation ROperation.new("swap",void,RParameter.new("other",self).add_flag(:IO))
25
- end
23
+ add_operation ROperation.new("compare",int,RParameter.new("other",self).to_const)
24
+ add_operation ROperation.new("swap",void,RParameter.new("other",self))
26
25
 
27
- def specialize_ruby
26
+ specialize_ruby do
28
27
  %Q$ def self.to_native(obj,context)
29
28
  if obj.is_a? ::String
30
29
  str = obj.to_str
@@ -36,6 +35,7 @@ module Rbind
36
35
  def to_s
37
36
  c_str
38
37
  end$
38
+ end
39
39
  end
40
40
  end
41
41
  end
@@ -0,0 +1,100 @@
1
+ module Rbind
2
+ class StdVector < RTemplateClass
3
+ def specialize(klass,*parameters)
4
+ if parameters.size != 1
5
+ raise ArgumentError,"StdVector does only support one template parameter. Got: #{parameters}}"
6
+ end
7
+ vector_type = parameters.flatten.first
8
+
9
+ klass.add_operation ROperation.new(klass.name,nil)
10
+ klass.add_operation ROperation.new(klass.name,nil,RParameter.new("other",klass).to_const)
11
+
12
+ para = Array.new
13
+ para << RParameter.new("size",type("size_t"))
14
+ para << RParameter.new("val",vector_type).default_value(vector_type.full_name+"()").to_const
15
+ klass.add_operation ROperation.new("resize",type("void"),para)
16
+ klass.add_operation ROperation.new("size",type("size_t"))
17
+ klass.add_operation ROperation.new("clear",type("void"))
18
+ klass.add_operation ROperation.new("capacity",type("size_t"))
19
+ klass.add_operation ROperation.new("empty",type("bool"))
20
+ klass.add_operation ROperation.new("reserve",type("void"),RParameter.new("size",type("size_t")))
21
+ klass.add_operation ROperation.new("operator[]",vector_type,RParameter.new("size",type("size_t")))
22
+ klass.add_operation ROperation.new("at",vector_type,RParameter.new("size",type("size_t")))
23
+ klass.add_operation ROperation.new("front",vector_type)
24
+ klass.add_operation ROperation.new("back",vector_type)
25
+ klass.add_operation ROperation.new("data",type("void *"))
26
+ klass.add_operation ROperation.new("push_back",type("void"),RParameter.new("other",vector_type).to_const)
27
+ klass.add_operation ROperation.new("pop_back",type("void"))
28
+ klass.add_operation ROperation.new("swap",type("void"),RParameter.new("other",klass))
29
+ # add ruby code to the front of the method
30
+ klass.operation("operator[]").specialize_ruby do
31
+ "validate_index(size)"
32
+ end
33
+ klass.operation("at").specialize_ruby do
34
+ "validate_index(size)"
35
+ end
36
+
37
+ specialize_ruby do
38
+ %Q$ def self.new(type,*args)
39
+ klass,elements = if type.class == Class
40
+ [type.name,[]]
41
+ else
42
+ e = Array(type) + args.flatten
43
+ args = []
44
+ [type.class.name,e]
45
+ end
46
+ #remove module name
47
+ klass = klass.split("::")
48
+ klass.shift if klass.size > 1
49
+ klass = klass.join("_")
50
+ raise ArgumentError,"no std::vector defined for \#{type}" unless self.const_defined?(klass)
51
+ v = self.const_get(klass).new(*args)
52
+ elements.each do |e|
53
+ v << e
54
+ end
55
+ v
56
+ end$
57
+ end
58
+
59
+ klass
60
+ end
61
+
62
+ # called from RTemplate when ruby_specialize is called for the instance
63
+ def specialize_ruby_specialization(klass)
64
+ %Q$ include Enumerable
65
+ alias get_element []
66
+ def [](idx)
67
+ validate_index(idx)
68
+ get_element(idx)
69
+ end
70
+
71
+ def validate_index(idx)
72
+ if idx < 0 || idx >= size
73
+ raise RangeError,"\#{idx} is out of range [0..\#{size-1}]"
74
+ end
75
+ end
76
+ def each(&block)
77
+ if block
78
+ s = size
79
+ 0.upto(s-1) do |i|
80
+ yield self[i]
81
+ end
82
+ else
83
+ Enumerator.new(self)
84
+ end
85
+ end
86
+ def <<(val)
87
+ push_back(val)
88
+ self
89
+ end
90
+ def delete_if(&block)
91
+ v = self.class.new
92
+ each do |i|
93
+ v << i if !yield(i)
94
+ end
95
+ v.swap(self)
96
+ self
97
+ end$
98
+ end
99
+ end
100
+ end
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'rbind'
3
- s.version = '0.0.16'
3
+ s.version = '0.0.17'
4
4
  s.date = '2013-08-13'
5
5
  s.platform = Gem::Platform::RUBY
6
6
  s.authors = ['Alexander Duda']
@@ -11,7 +11,7 @@ Gem::Specification.new do |s|
11
11
  'but is not tight to this library. It allows to import already wrapped types '\
12
12
  'from other gems/libraries using rbind to share the same types across '\
13
13
  'multiple gems/libraries. For now rbind uses a copy of the OpenCV python hdr_parser '\
14
- 'to parse c/c++ header files and looks for certain defines. '\
14
+ 'to parse c/c++ header files.'\
15
15
  'This gem is still under heavy development and the API might change in the future.'
16
16
  s.files = `git ls-files`.split("\n")
17
17
  s.require_path = 'lib'