rbplusplus 0.9.1 → 1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. data/Rakefile +4 -9
  2. data/lib/rbplusplus/builders/allocation_strategy.rb +0 -7
  3. data/lib/rbplusplus/builders/base.rb +11 -5
  4. data/lib/rbplusplus/builders/class.rb +5 -14
  5. data/lib/rbplusplus/builders/const.rb +1 -1
  6. data/lib/rbplusplus/builders/constructor.rb +1 -1
  7. data/lib/rbplusplus/builders/director.rb +13 -13
  8. data/lib/rbplusplus/builders/enumeration.rb +2 -2
  9. data/lib/rbplusplus/builders/helpers/class.rb +17 -2
  10. data/lib/rbplusplus/builders/helpers/implicit_caster.rb +0 -0
  11. data/lib/rbplusplus/builders/implicit_caster.rb +24 -0
  12. data/lib/rbplusplus/builders/instance_variable.rb +4 -4
  13. data/lib/rbplusplus/builders/method_base.rb +8 -7
  14. data/lib/rbplusplus/builders/module.rb +1 -1
  15. data/lib/rbplusplus/logger.rb +13 -4
  16. data/lib/rbplusplus/transformers/class.rb +43 -34
  17. data/lib/rbplusplus/transformers/constructor.rb +30 -0
  18. data/lib/rbplusplus/transformers/function.rb +3 -3
  19. data/lib/rbplusplus/transformers/method.rb +2 -2
  20. data/lib/rbplusplus/transformers/node.rb +10 -17
  21. data/lib/rbplusplus/writers/multiple_files_writer.rb +8 -6
  22. data/lib/rbplusplus.rb +2 -1
  23. data/test/allocation_strategies_test.rb +21 -14
  24. data/test/class_methods_encapsulate_test.rb +25 -25
  25. data/test/class_methods_test.rb +7 -12
  26. data/test/classes_test.rb +36 -40
  27. data/test/compiling_test.rb +23 -19
  28. data/test/constructors_test.rb +5 -5
  29. data/test/custom_code_test.rb +25 -32
  30. data/test/default_arguments_test.rb +38 -42
  31. data/test/director_test.rb +51 -53
  32. data/test/enumerations_test.rb +37 -41
  33. data/test/extension_test.rb +10 -10
  34. data/test/file_writers_test.rb +17 -21
  35. data/test/function_pointer_test.rb +9 -13
  36. data/test/function_pointers_classes_test.rb +7 -11
  37. data/test/functions_test.rb +4 -10
  38. data/test/generated/extconf.rb +2 -2
  39. data/test/headers/alloc_strats.h +3 -1
  40. data/test/headers/implicit_cast.h +107 -0
  41. data/test/headers/to_from_ruby.h +13 -6
  42. data/test/headers/to_from_ruby_source.cpp +2 -2
  43. data/test/implicit_cast_test.rb +67 -0
  44. data/test/modules_test.rb +39 -40
  45. data/test/nested_test.rb +14 -16
  46. data/test/overloading_test.rb +17 -20
  47. data/test/struct_test.rb +4 -6
  48. data/test/subclass_test.rb +10 -12
  49. data/test/test_helper.rb +21 -12
  50. data/test/to_from_ruby_test.rb +7 -1
  51. data/test/wrap_as_test.rb +32 -29
  52. metadata +170 -108
  53. data/lib/rbplusplus/transformers/node_cache.rb +0 -15
data/Rakefile CHANGED
@@ -3,7 +3,7 @@ require 'rake/rdoctask'
3
3
  require 'rake/contrib/sshpublisher'
4
4
 
5
5
  PROJECT_NAME = "rb++"
6
- RBPLUSPLUS_VERSION = "0.9.1"
6
+ RBPLUSPLUS_VERSION = "1.0"
7
7
 
8
8
  task :default => :test
9
9
 
@@ -70,14 +70,11 @@ spec = Gem::Specification.new do |s|
70
70
 
71
71
  s.description = <<-END
72
72
  Rb++ combines the powerful query interface of rbgccxml and the Rice library to
73
- make Ruby wrapping extensions easier to write than ever.
73
+ make Ruby wrapping extensions of C++ libraries easier to write than ever.
74
74
  END
75
75
 
76
- s.add_dependency "rbgccxml", "~> 0.9"
77
- s.add_dependency "rice", "~> 1.3.0"
78
-
79
- s.add_development_dependency "test-unit", "1.2.3"
80
- s.add_development_dependency "mocha", "~> 0.9"
76
+ s.add_dependency "rbgccxml", "~> 1.0"
77
+ s.add_dependency "rice", "~> 1.4.0"
81
78
 
82
79
  patterns = [
83
80
  'TODO',
@@ -93,6 +90,4 @@ make Ruby wrapping extensions easier to write than ever.
93
90
  end
94
91
 
95
92
  Rake::GemPackageTask.new(spec) do |pkg|
96
- pkg.need_zip = true
97
- pkg.need_tar = true
98
93
  end
@@ -27,7 +27,6 @@ module RbPlusPlus
27
27
  namespace Rice {
28
28
  template<>
29
29
  struct Default_Allocation_Strategy< #{node_name} > {
30
- static #{node_name} * allocate();
31
30
  static void free(#{node_name} * obj);
32
31
  };
33
32
  }
@@ -37,12 +36,6 @@ namespace Rice {
37
36
 
38
37
  pre = "Rice::Default_Allocation_Strategy< #{node_name} >::"
39
38
 
40
- tmp = "#{node_name} * #{pre}allocate() { return "
41
- tmp += @public_constructor ? "new #{node_name};" : "NULL;"
42
- tmp += " }"
43
-
44
- registrations << tmp
45
-
46
39
  tmp = "void #{pre}free(#{node_name} * obj) { "
47
40
  tmp += @public_destructor ? "delete obj;" : ""
48
41
  tmp += " }"
@@ -64,8 +64,7 @@ module RbPlusPlus
64
64
  raise "Nodes must implement #build"
65
65
  end
66
66
 
67
- # After #build has run, this then triggers the actual generation of the C++
68
- # code and returns the final string.
67
+ # After #build has run, this then triggers the actual generation of the C++ code
69
68
  # All nodes must implement this.
70
69
  def write
71
70
  raise "Nodes must implement #write"
@@ -84,7 +83,13 @@ module RbPlusPlus
84
83
  # up sorted farther down the list
85
84
  @nodes =
86
85
  @nodes.sort_by do |a|
87
- a.is_a?(ClassNode) ? superclass_count(a.code) : 0
86
+ if a.is_a?(ClassNode)
87
+ superclass_count(a.code)
88
+ elsif a.is_a?(ImplicitCasterNode) # Hmm, hack
89
+ 1_000_000
90
+ else
91
+ 0
92
+ end
88
93
  end
89
94
  end
90
95
 
@@ -111,7 +116,8 @@ module RbPlusPlus
111
116
  node.ignored? ||
112
117
  (node.moved_to && node.moved_to != self.code) ||
113
118
  !node.public? ||
114
- (node.is_a?(RbGCCXML::Struct) && node.incomplete?)
119
+ (node.is_a?(RbGCCXML::Struct) && node.incomplete?) ||
120
+ node.is_a?(RbGCCXML::FundamentalType)
115
121
  end
116
122
 
117
123
  # Given a new node, build it and add it to our nodes list
@@ -142,7 +148,7 @@ module RbPlusPlus
142
148
  if !node._disable_typedef_lookup?
143
149
  while found
144
150
  last_found = found
145
- typedef = RbGCCXML::XMLParsing.find(:node_type => "Typedef", :type => found.attributes["id"])
151
+ typedef = RbGCCXML::NodeCache.all("Typedef").select {|t| t.attributes["type"] == found.attributes["id"]}.first
146
152
 
147
153
  # Some typedefs have the access attribute, some don't. We want those without the attribute
148
154
  # and those with the access="public". For this reason, we can't put :access => "public" in the
@@ -54,10 +54,6 @@ module RbPlusPlus
54
54
  unless @director
55
55
  check_allocation_strategies
56
56
  end
57
-
58
- # For now, build a const& type converter for all class types until Rice has
59
- # better management of to_ruby of class types, if it ever happens
60
- add_global_child ConstConverterNode.new(self.code, self)
61
57
  end
62
58
 
63
59
  def write
@@ -70,10 +66,10 @@ module RbPlusPlus
70
66
  class_names = class_names.join(",")
71
67
 
72
68
  if parent.rice_variable
73
- registrations << "#{prefix} Rice::define_class_under< #{class_names} >" +
69
+ registrations << "\t#{prefix} Rice::define_class_under< #{class_names} >" +
74
70
  "(#{parent.rice_variable}, \"#{ruby_name}\");"
75
71
  else
76
- registrations << "#{prefix} Rice::define_class< #{class_names} >(\"#{ruby_name}\");"
72
+ registrations << "\t#{prefix} Rice::define_class< #{class_names} >(\"#{ruby_name}\");"
77
73
  end
78
74
 
79
75
  handle_custom_code
@@ -83,7 +79,6 @@ module RbPlusPlus
83
79
 
84
80
  # Here we take the code manually added to the extension via #add_custom_code
85
81
  def handle_custom_code
86
-
87
82
  # Any declaration code, usually wrapper function definitions
88
83
  self.code._get_custom_declarations.flatten.each do |decl|
89
84
  declarations << decl
@@ -91,7 +86,7 @@ module RbPlusPlus
91
86
 
92
87
  # And the registration code to hook into Rice
93
88
  self.code._get_custom_wrappings.flatten.each do |wrap|
94
- registrations << "#{wrap.gsub(/<class>/, self.rice_variable)}"
89
+ registrations << "\t#{wrap.gsub(/<class>/, self.rice_variable)}"
95
90
  end
96
91
  end
97
92
 
@@ -105,16 +100,12 @@ module RbPlusPlus
105
100
  # We check here if we're one of those classes and completely skip this step
106
101
  return if [self.code.constructors].flatten.empty?
107
102
 
108
- # Find a public default constructor
109
- found = [self.code.constructors.find(:arguments => [], :access => "public")].flatten
110
- has_public_constructor = !found.empty?
111
-
112
103
  # See if the destructor is public
113
104
  has_public_destructor = self.code.destructor && self.code.destructor.public?
114
105
 
115
- if !has_public_constructor || !has_public_destructor
106
+ if !has_public_destructor
116
107
  add_global_child AllocationStrategyNode.new(self,
117
- self.code, has_public_constructor, has_public_destructor)
108
+ self.code, true, has_public_destructor)
118
109
  end
119
110
  end
120
111
 
@@ -20,7 +20,7 @@ module RbPlusPlus
20
20
  end
21
21
 
22
22
  prefix = parent.rice_variable ? "#{parent.rice_variable}." : "Rice::Module(rb_mKernel)."
23
- registrations << "#{prefix}const_set(\"#{code.name}\", to_ruby(#{set_to}));"
23
+ registrations << "\t#{prefix}const_set(\"#{code.name}\", to_ruby(#{set_to}));"
24
24
  end
25
25
 
26
26
  end
@@ -10,7 +10,7 @@ module RbPlusPlus
10
10
 
11
11
  def write
12
12
  args = [code.parent.qualified_name, code.arguments.map {|a| a.cpp_type.to_cpp }].flatten.compact
13
- registrations << "#{parent.rice_variable}.define_constructor(Rice::Constructor< #{args.join(",")} >());"
13
+ registrations << "\t#{parent.rice_variable}.define_constructor(Rice::Constructor< #{args.join(",")} >());"
14
14
  end
15
15
 
16
16
  end
@@ -27,7 +27,7 @@ module RbPlusPlus
27
27
  def build
28
28
  add_child IncludeNode.new(self, "rice/Director.hpp", :global)
29
29
  add_child IncludeNode.new(self, "rice/Constructor.hpp", :global)
30
-
30
+
31
31
  # To ensure proper compilation, this director class needs
32
32
  # to implement all pure virtual methods found up the
33
33
  # inheritance heirarchy of this class. So here, we traverse
@@ -68,15 +68,15 @@ module RbPlusPlus
68
68
  end
69
69
  end
70
70
 
71
- declarations << "#{@name}(#{args.join(", ")}) : #{@class_qualified_name}(#{supercall_args.join(", ")}), Rice::Director(self) { }"
71
+ declarations << "\t\t#{@name}(#{args.join(", ")}) : #{@class_qualified_name}(#{supercall_args.join(", ")}), Rice::Director(self) { }"
72
72
 
73
- registrations << "#{self.parent.rice_variable}.define_director< #{@name} >();"
74
- registrations << "#{self.parent.rice_variable}.define_constructor(Rice::Constructor< #{types.join(", ")} >());"
73
+ registrations << "\t#{self.parent.rice_variable}.define_director< #{@name} >();"
74
+ registrations << "\t#{self.parent.rice_variable}.define_constructor(Rice::Constructor< #{types.join(", ")} >());"
75
75
  end
76
76
 
77
77
  def write
78
78
  declarations << "class #{@name} : public #{@class_qualified_name}, public Rice::Director {"
79
- declarations << "public:"
79
+ declarations << "\tpublic:"
80
80
 
81
81
  # Handle constructors
82
82
  if @constructors.empty?
@@ -104,7 +104,7 @@ module RbPlusPlus
104
104
  def_arguments = def_arguments.length == 0 ? "" : def_arguments.join(", ")
105
105
 
106
106
  reverse = ""
107
- up_or_raise =
107
+ up_or_raise =
108
108
  if method.default_return_value
109
109
  reverse = "!"
110
110
  "return #{method.default_return_value}"
@@ -123,17 +123,17 @@ module RbPlusPlus
123
123
 
124
124
  # Write out the virtual method that forwards calls into Ruby
125
125
  declarations << ""
126
- declarations << "virtual #{return_type} #{cpp_name}(#{def_arguments}) #{const} {"
127
- declarations << "#{call_down};"
128
- declarations << "}"
126
+ declarations << "\t\tvirtual #{return_type} #{cpp_name}(#{def_arguments}) #{const} {"
127
+ declarations << "\t\t\t#{call_down};"
128
+ declarations << "\t\t}"
129
129
 
130
130
  # Write out the wrapper method that gets exposed to Ruby that handles
131
131
  # going up the inheritance chain
132
132
  declarations << ""
133
- declarations << "#{return_type} default_#{cpp_name}(#{def_arguments}) #{const} {"
134
- declarations << "#{up_or_raise};"
135
- declarations << "}"
136
-
133
+ declarations << "\t\t#{return_type} default_#{cpp_name}(#{def_arguments}) #{const} {"
134
+ declarations << "\t\t\t#{up_or_raise};"
135
+ declarations << "\t\t}"
136
+
137
137
  end
138
138
 
139
139
  declarations << "};"
@@ -20,11 +20,11 @@ module RbPlusPlus
20
20
  def write
21
21
  second = parent.rice_variable ? ", #{parent.rice_variable}" : ""
22
22
 
23
- registrations << "#{rice_variable_type} #{rice_variable} = " \
23
+ registrations << "\t#{rice_variable_type} #{rice_variable} = " \
24
24
  "Rice::define_enum<#{code.qualified_name}>(\"#{code.name}\"#{second});"
25
25
 
26
26
  code.values.each do |v|
27
- registrations << "#{rice_variable}.define_value(\"#{v.name}\", #{v.qualified_name});"
27
+ registrations << "\t#{rice_variable}.define_value(\"#{v.name}\", #{v.qualified_name});"
28
28
  end
29
29
  end
30
30
 
@@ -35,8 +35,6 @@ module RbPlusPlus
35
35
  "please use #use_contructor to select which one to use."
36
36
  end
37
37
 
38
- # First, lets see if we have any non-generated constructors
39
-
40
38
  [to_use || real_constructors].flatten.each do |constructor|
41
39
  next if do_not_wrap?(constructor)
42
40
 
@@ -44,6 +42,15 @@ module RbPlusPlus
44
42
  next if ignore_artificial || constructor.arguments.length == 1
45
43
  end
46
44
 
45
+ if implicit_converter?(constructor)
46
+ if constructor.implicit_casting?
47
+ parent.add_child ImplicitCasterNode.new(constructor, self)
48
+ end
49
+
50
+ # We don't want to expose these constructors to Rice
51
+ next
52
+ end
53
+
47
54
  if @director
48
55
  @director.wrap_constructor constructor
49
56
  else
@@ -52,6 +59,14 @@ module RbPlusPlus
52
59
  end
53
60
  end
54
61
 
62
+ # Is this constructor a converter constructor?
63
+ def implicit_converter?(constructor)
64
+ # Single argument
65
+ constructor.arguments.length == 1 &&
66
+ # We are wrapping the type converting from
67
+ !do_not_wrap?(constructor.arguments[0].cpp_type.base_type)
68
+ end
69
+
55
70
  # Wrap up any class constants
56
71
  def with_constants
57
72
  [self.code.constants].flatten.each do |const|
@@ -0,0 +1,24 @@
1
+ module RbPlusPlus
2
+ module Builders
3
+
4
+ class ImplicitCasterNode < Base
5
+
6
+ def initialize(constructor, parent)
7
+ super(constructor, parent)
8
+
9
+ @to = parent.code.qualified_name
10
+ @from = constructor.arguments[0].cpp_type.base_type.qualified_name
11
+ end
12
+
13
+ def build
14
+ end
15
+
16
+ def write
17
+ if @from != @to
18
+ registrations << "\tRice::define_implicit_cast< #{@from}, #{@to} >();"
19
+ end
20
+ end
21
+ end
22
+
23
+ end
24
+ end
@@ -15,19 +15,19 @@ module RbPlusPlus
15
15
  if !code.cpp_type.const?
16
16
  method_name = "wrap_#{parent_name}_#{code.name}_set"
17
17
  declarations << "void #{method_name}(#{parent.code.qualified_name}* self, #{code.cpp_type.to_cpp} val) {"
18
- declarations << "self->#{code.name} = val;"
18
+ declarations << "\tself->#{code.name} = val;"
19
19
  declarations << "}"
20
20
 
21
- registrations << "#{parent.rice_variable}.define_method(\"#{ruby_name}=\", &#{method_name});"
21
+ registrations << "\t#{parent.rice_variable}.define_method(\"#{ruby_name}=\", &#{method_name});"
22
22
  end
23
23
 
24
24
  # Getter
25
25
  method_name = "wrap_#{parent_name}_#{code.name}_get"
26
26
  declarations << "#{code.cpp_type.to_cpp} #{method_name}(#{parent.code.qualified_name}* self) {"
27
- declarations << "return self->#{code.name};"
27
+ declarations << "\treturn self->#{code.name};"
28
28
  declarations << "}"
29
29
 
30
- registrations << "#{parent.rice_variable}.define_method(\"#{ruby_name}\", &#{method_name});"
30
+ registrations << "\t#{parent.rice_variable}.define_method(\"#{ruby_name}\", &#{method_name});"
31
31
  end
32
32
 
33
33
  end
@@ -72,9 +72,9 @@ module RbPlusPlus
72
72
 
73
73
  funcall = "rb_funcall(#{block_var_name}, rb_intern(\"call\"), #{callback_values.join(", ")})"
74
74
  if return_type == "void"
75
- declarations << "#{funcall};"
75
+ declarations << "\t#{funcall};"
76
76
  else
77
- declarations << "return from_ruby<#{return_type} >(#{funcall});"
77
+ declarations << "\treturn from_ruby<#{return_type} >(#{funcall});"
78
78
  end
79
79
 
80
80
  declarations << "}"
@@ -96,7 +96,7 @@ module RbPlusPlus
96
96
  declarations << "\treturn Qnil;"
97
97
  declarations << "}"
98
98
 
99
- registrations << "#{self.prefix}#{self.rice_method}(\"#{@ruby_name + self.suffix}\", &#{wrapper_func});"
99
+ registrations << "\t#{self.prefix}#{self.rice_method}(\"#{@ruby_name + self.suffix}\", &#{wrapper_func});"
100
100
  end
101
101
 
102
102
  def wrap_normal_method
@@ -137,13 +137,14 @@ module RbPlusPlus
137
137
 
138
138
  const = self.code.const? ? " const" : ""
139
139
 
140
- registrations << "{"
140
+ registrations << ""
141
+ registrations << "\t{"
141
142
 
142
- registrations << "typedef #{return_type} ( #{method_ref} )( #{arguments.join(", ")} )#{const};"
143
- registrations << "#{self.prefix}#{self.rice_method}(\"#{@ruby_name + self.suffix}\", " +
143
+ registrations << "\t\ttypedef #{return_type} ( #{method_ref} )( #{arguments.join(", ")} )#{const};"
144
+ registrations << "\t\t#{self.prefix}#{self.rice_method}(\"#{@ruby_name + self.suffix}\", " +
144
145
  "#{usage_ref}( &#{code_path} )#{def_args});"
145
146
 
146
- registrations << "}"
147
+ registrations << "\t}"
147
148
  end
148
149
 
149
150
  # See http://www.gccxml.org/Bug/view.php?id=9234
@@ -45,7 +45,7 @@ module RbPlusPlus
45
45
  end
46
46
 
47
47
  def write
48
- prefix = "#{rice_variable_type} #{rice_variable} = "
48
+ prefix = "\t#{rice_variable_type} #{rice_variable} = "
49
49
 
50
50
  if parent.rice_variable
51
51
  registrations << "#{prefix} Rice::define_module_under(#{parent.rice_variable}, \"#{@name}\");"
@@ -15,6 +15,10 @@ module RbPlusPlus
15
15
  @@quiet = val
16
16
  end
17
17
 
18
+ def silent!
19
+ @@silent = true
20
+ end
21
+
18
22
  def verbose?
19
23
  @@verbose = false unless defined?(@@verbose)
20
24
  @@verbose
@@ -25,20 +29,25 @@ module RbPlusPlus
25
29
  @@quiet
26
30
  end
27
31
 
32
+ def silent?
33
+ @@silent = false unless defined?(@@silent)
34
+ @@silent
35
+ end
36
+
28
37
  def info(msg)
29
- $stdout.puts "(INFO) #{msg}" unless quiet?
38
+ $stdout.puts "(INFO) #{msg}" if !quiet? && !silent?
30
39
  end
31
40
 
32
41
  def warn(type, msg)
33
- $stdout.puts "(WARNING) #{msg}"
42
+ $stdout.puts "(WARNING) #{msg}" if !silent?
34
43
  end
35
44
 
36
45
  def debug(msg)
37
- $stdout.puts "(DEBUG) #{msg}" if verbose?
46
+ $stdout.puts "(DEBUG) #{msg}" if verbose? && !silent?
38
47
  end
39
48
 
40
49
  def error(msg)
41
- $stderr.puts "(ERROR) #{msg}"
50
+ $stderr.puts "(ERROR) #{msg}" if !silent?
42
51
  end
43
52
  end
44
53
  end
@@ -1,11 +1,22 @@
1
1
  module RbGCCXML
2
2
  class Class < Node
3
+
4
+ def initialize(*args)
5
+ super
6
+
7
+ @included_classes = []
8
+ @included_methods = []
9
+
10
+ @declarations = []
11
+ @wrappings = []
12
+ end
13
+
3
14
  # Class can include nested classes and nested structs.
4
15
  #
5
16
  # Class can also include external methods/functions as class level methods
6
17
  # also supports instance level methods
7
18
  #
8
- # ex.
19
+ # ex.
9
20
  #
10
21
  # math_class.includes node.namespaces("Math").functions("mod")
11
22
  #
@@ -19,23 +30,21 @@ module RbGCCXML
19
30
  #
20
31
  def includes(val)
21
32
  if (val.is_a?(RbGCCXML::Struct) || val.is_a?(RbGCCXML::Class))
22
- cache[:classes] ||= []
23
- cache[:classes] << val
33
+ @included_classes << val
24
34
  else
25
- cache[:methods] ||= []
26
- cache[:methods] << val
35
+ @included_methods << val
27
36
  end
28
37
  val.moved_to = self
29
38
  end
30
-
39
+
31
40
  alias_method :node_classes, :classes
32
41
  def classes(*args) #:nodoc:
33
- find_with_cache(:classes, node_classes(*args))
42
+ find_with(node_classes(*args), @included_classes)
34
43
  end
35
44
 
36
45
  alias_method :node_methods, :methods
37
46
  def methods(*args) #:nodoc:
38
- find_with_cache(:methods, node_methods(*args))
47
+ find_with(node_methods(*args), @included_methods)
39
48
  end
40
49
 
41
50
  # Specify which superclass to use.
@@ -45,42 +54,42 @@ module RbGCCXML
45
54
  # where this method hasn't been used yet.
46
55
  #
47
56
  # klass should be the node for the class you want to wrap
48
- def use_superclass(node)
49
- cache[:use_superclass] = node
57
+ def use_superclass(klass)
58
+ @use_superclass = klass
50
59
  end
51
60
 
52
61
  def _get_superclass #:nodoc:
53
- cache[:use_superclass]
62
+ @use_superclass
54
63
  end
55
64
 
56
- # Like #use_superclass, this method allows the user to specify
57
- # which constructor Rice should expose to Ruby.
58
- # Rice currently, because of the lack of method overloading,
65
+ # Like #use_superclass, this method allows the user to specify
66
+ # which constructor Rice should expose to Ruby.
67
+ # Rice currently, because of the lack of method overloading,
59
68
  # only supports one constructor definition. Having multiple
60
69
  # in the code will work, but only the last defined will actually
61
- # work.
70
+ # work.
62
71
  def use_constructor(node)
63
- cache[:use_constructor] = node
72
+ @use_constructor = node
64
73
  end
65
74
 
66
75
  def _get_constructor #:nodoc:
67
- cache[:use_constructor]
76
+ @use_constructor
68
77
  end
69
78
 
70
79
  # Sometimes, type manipulation, moving nodes around, or flat
71
80
  # ignoring nodes just doesn't do the trick and you need to write
72
81
  # your own custom wrapper code. This method is for that. There are
73
- # two parts to custom code: the declaration and the wrapping.
82
+ # two parts to custom code: the declaration and the wrapping.
74
83
  #
75
84
  # The Declaration:
76
85
  # This is the actual custom code you write. It may need to take
77
86
  # a pointer to the class type as the first parameter
78
- # and follow with that any parameters you want.
87
+ # and follow with that any parameters you want.
79
88
  #
80
89
  # The Wrapping
81
90
  # The wrapping is the custom (usually one-line) bit of Rice code that
82
91
  # hooks up your declaration with the class in question. To ensure that
83
- # you doesn't need to know the variable of the ruby class object,
92
+ # you doesn't need to know the variable of the ruby class object,
84
93
  # use <class> and rb++ will replace it as needed.
85
94
  #
86
95
  # Example (taken from Ogre.rb's wrapping of Ogre)
@@ -100,45 +109,45 @@ module RbGCCXML
100
109
  # of times for a class, it won't clobber any previous uses.
101
110
  #
102
111
  def add_custom_code(declaration, wrapping)
103
- cache[:declarations] ||= []
104
- cache[:declarations] << declaration
105
-
106
- cache[:wrappings] ||= []
107
- cache[:wrappings] << wrapping
112
+ @declarations << declaration
113
+ @wrappings << wrapping
108
114
  end
109
115
 
110
116
  def _get_custom_declarations #:nodoc:
111
- cache[:declarations] || []
117
+ @declarations
112
118
  end
113
119
 
114
120
  def _get_custom_wrappings #:nodoc:
115
- cache[:wrappings] || []
121
+ @wrappings
116
122
  end
117
123
 
118
124
  # Does this class have virtual methods (especially pure virtual?)
119
- # If so, then rb++ will generate a proxy class to handle
125
+ # If so, then rb++ will generate a proxy class to handle
120
126
  # the message routing as needed.
121
127
  def needs_director? #:nodoc:
122
- !!cache[:build_director] #[methods].flatten.select {|m| m.virtual? }.length > 0
128
+ !!@build_director
123
129
  end
124
130
 
125
131
  # Until all the kinks of the director code generation can be
126
132
  # worked out, rb++ must be told which classes to build
127
133
  # directors for. Simply call this method on the class to do so
128
134
  def director
129
- cache[:build_director] = true
135
+ @build_director = true
136
+ end
137
+
138
+ # See RbGCCXML::Constructor::implicit_casting
139
+ def implicit_casting(state)
140
+ self.constructors.each {|c| c.implicit_casting(state) }
130
141
  end
131
142
 
132
143
  private
133
144
 
134
145
  # Take the cache key, and the normal results, adds to the results
135
146
  # those that are in the cache and returns them properly.
136
- def find_with_cache(type, results)
137
- in_cache = cache[type]
138
-
147
+ def find_with(results, with = nil)
139
148
  ret = QueryResult.new
140
149
  ret << results if results
141
- ret << in_cache if in_cache
150
+ ret << with if with
142
151
  ret.flatten!
143
152
 
144
153
  ret.size == 1 ? ret[0] : ret
@@ -0,0 +1,30 @@
1
+ module RbGCCXML
2
+ class Constructor < Function
3
+
4
+ # See:
5
+ # http://msdn.microsoft.com/en-us/library/h1y7x448.aspx
6
+ # http://msdn.microsoft.com/en-us/library/s2ff0fz8(VS.100).aspx
7
+ #
8
+ # Single argument constructors of a class are called Conversion constructors.
9
+ # They manage the conversion of one type to another. Rice handles this functionality
10
+ # through a special method, define_implicit_cast<From, To>().
11
+ #
12
+ # Rb++ attempts to find all classes and constructors that fit this pattern
13
+ # and write out the casting declarations as needed. In the cases where this is
14
+ # functionality not wanted, use this method to turn off this casting check.
15
+ #
16
+ # This method can be called per Constructor or per Class.
17
+ def implicit_casting(state)
18
+ @implicit_casting = state
19
+ end
20
+
21
+ def implicit_casting? #:nodoc:
22
+ if @implicit_casting.nil?
23
+ @implicit_casting = true
24
+ end
25
+
26
+ @implicit_casting
27
+ end
28
+
29
+ end
30
+ end
@@ -2,19 +2,19 @@ module RbGCCXML
2
2
  class Function < Node
3
3
  # Always true for functions, false for methods
4
4
  def static?
5
- !cache[:as_method]
5
+ !@as_method
6
6
  end
7
7
 
8
8
  # Sets this function to be an instance method.
9
9
  # Useful for custom function declaration.
10
10
  def as_instance_method
11
- cache[:as_method] = true
11
+ @as_method = true
12
12
  self
13
13
  end
14
14
 
15
15
  # Are we wrapping this function as an instance method?
16
16
  def as_instance_method?
17
- !!cache[:as_method]
17
+ !!@as_method
18
18
  end
19
19
 
20
20
  # For Class#needs_director?