rbplusplus 0.1.1 → 0.8

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/Rakefile +31 -15
  2. data/TODO +20 -0
  3. data/lib/rbplusplus/builders/base.rb +148 -8
  4. data/lib/rbplusplus/builders/class.rb +106 -31
  5. data/lib/rbplusplus/builders/enumeration.rb +40 -0
  6. data/lib/rbplusplus/builders/extension.rb +31 -6
  7. data/lib/rbplusplus/builders/module.rb +12 -6
  8. data/lib/rbplusplus/builders/types_manager.rb +93 -0
  9. data/lib/rbplusplus/extension.rb +69 -41
  10. data/lib/rbplusplus/module.rb +3 -1
  11. data/lib/rbplusplus/transformers/class.rb +67 -0
  12. data/lib/rbplusplus/transformers/constructor.rb +4 -0
  13. data/lib/rbplusplus/transformers/function.rb +27 -0
  14. data/lib/rbplusplus/transformers/method.rb +4 -0
  15. data/lib/rbplusplus/transformers/module.rb +71 -0
  16. data/lib/rbplusplus/transformers/node.rb +77 -0
  17. data/lib/rbplusplus/transformers/node_cache.rb +19 -0
  18. data/lib/rbplusplus/transformers/node_reference.rb +30 -0
  19. data/lib/rbplusplus/transformers/rbgccxml.rb +6 -0
  20. data/lib/rbplusplus/writers/extension.rb +33 -25
  21. data/lib/rbplusplus/writers/multiple_files_writer.rb +42 -2
  22. data/lib/rbplusplus/writers/single_file_writer.rb +5 -0
  23. data/lib/rbplusplus.rb +24 -0
  24. data/test/class_methods_test.rb +55 -0
  25. data/test/classes_test.rb +0 -25
  26. data/test/compiling_test.rb +30 -0
  27. data/test/constructors_test.rb +40 -0
  28. data/test/enumerations_test.rb +63 -0
  29. data/test/file_writers_test.rb +56 -4
  30. data/test/generated/extconf.rb +25 -5
  31. data/test/headers/class_methods.h +41 -0
  32. data/test/headers/complex_static_methods.h +25 -0
  33. data/test/headers/constructors.h +47 -0
  34. data/test/headers/enums.h +77 -0
  35. data/test/headers/external_mapping.h +16 -0
  36. data/test/headers/external_mapping_rice.h +20 -0
  37. data/test/headers/include/helper.h +1 -0
  38. data/test/headers/nested_struct.h +20 -0
  39. data/test/headers/overload.h +28 -0
  40. data/test/headers/subclass.h +42 -0
  41. data/test/headers/to_from_ruby.h +78 -0
  42. data/test/headers/to_from_ruby_source.cpp +22 -0
  43. data/test/headers/ugly_helper.h +18 -0
  44. data/test/headers/ugly_interface.h +115 -0
  45. data/test/headers/ugly_interface_ns.h +8 -0
  46. data/test/nested_test.rb +26 -0
  47. data/test/object_persistence_test.rb +44 -0
  48. data/test/overloading_test.rb +36 -0
  49. data/test/struct_test.rb +22 -0
  50. data/test/subclass_test.rb +31 -0
  51. data/test/test_helper.rb +5 -0
  52. data/test/to_from_ruby_test.rb +24 -0
  53. data/test/wrap_as_test.rb +114 -0
  54. metadata +43 -6
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.1.1"
6
+ RBPLUSPLUS_VERSION = "0.8"
7
7
 
8
8
  task :default => :test
9
9
 
@@ -11,12 +11,15 @@ task :default => :test
11
11
  # The tests wrap and load C++ wrapper code constantly.
12
12
  # When running all the tests at once, we very quickly run
13
13
  # into problems where Rice crashes because
14
- # a given C++ class is already wrapped. So we need to run the
14
+ # a given C++ class is already wrapped, or glibc doesn't like our
15
+ # unorthodox handling of it's pieces. So we need to run the
15
16
  # tests individually
16
17
  desc "Run the tests"
17
18
  task :test do
18
- FileList["test/*_test.rb"].each do |file|
19
- ruby file
19
+ files = FileList["test/*_test.rb"]
20
+ puts files.inspect
21
+ files.each do |file|
22
+ sh "ruby #{file}"
20
23
  end
21
24
  end
22
25
 
@@ -31,16 +34,29 @@ end
31
34
  RUBYFORGE_USERNAME = "jameskilton"
32
35
  PROJECT_WEB_PATH = "/var/www/gforge-projects/rbplusplus"
33
36
 
34
- desc "Update the website"
35
- task :upload_web => :rdoc do |t|
36
- unless File.directory?("publish")
37
- mkdir "publish"
38
- mkdir "publish/rbplusplus"
37
+ namespace :web do
38
+ desc "Build website"
39
+ task :build => :rdoc do |t|
40
+ cd "website" do
41
+ sh "webgen"
42
+ end
43
+
44
+ unless File.directory?("publish")
45
+ mkdir "publish"
46
+ end
47
+ sh "cp -r website/output/* publish/"
48
+ sh "cp -r html/* publish/rbplusplus/"
49
+ end
50
+
51
+ desc "Update the website"
52
+ task :upload => "web:build" do |t|
53
+ Rake::SshDirPublisher.new("#{RUBYFORGE_USERNAME}@rubyforge.org", PROJECT_WEB_PATH, "publish").upload
54
+ end
55
+
56
+ desc "Clean up generated website files"
57
+ task :clean do
58
+ rm_rf "publish"
39
59
  end
40
- sh "cp -r website publish/"
41
- sh "cp -r html/* publish/rbplusplus/"
42
- Rake::SshDirPublisher.new("#{RUBYFORGE_USERNAME}@rubyforge.org", PROJECT_WEB_PATH, "publish").upload
43
- rm_rf "publish"
44
60
  end
45
61
 
46
62
  spec = Gem::Specification.new do |s|
@@ -57,8 +73,8 @@ Rb++ combines the powerful query interface of rbgccxml and the Rice library to
57
73
  make Ruby wrapping extensions easier to write than ever.
58
74
  END
59
75
 
60
- s.add_dependency "rbgccxml", "0.1.1"
61
- s.add_dependency "rice", "1.0.1"
76
+ s.add_dependency "rbgccxml", "0.8"
77
+ s.add_dependency "rice", ">= 1.0.2"
62
78
 
63
79
  patterns = [
64
80
  'TODO',
data/TODO CHANGED
@@ -3,6 +3,21 @@ TODO
3
3
  * Allowing use of "have_library"
4
4
  * Other mkmf functions?
5
5
 
6
+ * rbgccxml: Continue working with QueryResult#find, making it as powerful
7
+ and robust as possible.
8
+
9
+ * Rest of the GCCXML types (as needed):
10
+ - ArrayType
11
+ - Converter
12
+ - Destructor
13
+ - Field
14
+ - FunctionType
15
+ - OperatorFunction
16
+ - OperatorMethod
17
+ - OffsetType
18
+ - Union
19
+ - Variable
20
+
6
21
  STARTED
7
22
  * Adding constructor
8
23
  - Test constructor arguments
@@ -18,6 +33,11 @@ DONE
18
33
  * Adding classes to classes (ad infinitum)
19
34
  * Look into file naming when dealing with Modules
20
35
  * Nested Modules
36
+ * Recognizing and building to_ruby / from_ruby methods for const type references
37
+ * Moving the to_ruby / from_ruby definitions to a place that all will know about them
38
+ * Enumerations
39
+ * Proper TypesManager dealings with single_file writer mode
40
+ * Working with the defined C++ heirarchy chain
21
41
 
22
42
  No longer waiting on rice - just building a wrapper myself now.
23
43
  * Adding global methods (Kernel-level methods)
@@ -54,6 +54,91 @@ module RbPlusPlus
54
54
  @includes = []
55
55
  @declarations = []
56
56
  @body = []
57
+ @registered_nodes = []
58
+ end
59
+
60
+ # adds a register function to the Init or register of this node
61
+ def register_node(node, register_func)
62
+ @registered_nodes << [node, register_func]
63
+ end
64
+
65
+ private
66
+
67
+ def nested_level(node, level=0)
68
+ return level if node.is_a?(RbGCCXML::Namespace) || node.is_a?(RbGCCXML::Enumeration)
69
+ return level if node.super_classes.length == 0
70
+ node.super_classes.each do |sup|
71
+ level = nested_level(sup, level+1)
72
+ end
73
+ return level
74
+ end
75
+
76
+ public
77
+
78
+ # Sorts the registered nodes by hierachy, registering the base classes
79
+ # first.
80
+ #
81
+ # this is necessary for Rice to know about inheritance
82
+ def registered_nodes
83
+ #sort by hierachy
84
+ nodes = @registered_nodes.sort_by do |build, func|
85
+ if build.node.nil?
86
+ 0
87
+ else
88
+ nested_level(build.node)
89
+ end
90
+ end
91
+
92
+ #collect the sorted members
93
+ nodes.collect do |node, func|
94
+ func
95
+ end
96
+ end
97
+
98
+ # The name of the header file to include
99
+ # This is the file default, so long as it matches one of the export files
100
+ # If not this returns all exported files.
101
+ #
102
+ # This was added to workaround badly declared namespaces
103
+ def header_files(node)
104
+ file = node.file_name(false)
105
+ return [file] if self.class.sources.include?(file)
106
+ self.class.sources
107
+ end
108
+
109
+ # Adds the necessary includes in order to compile the specified node
110
+ def add_includes_for(node)
111
+ header_files(node).each do |header|
112
+ includes << "#include \"#{header}\""
113
+ end
114
+ end
115
+
116
+ # Include any user specified include files
117
+ def add_additional_includes
118
+ self.class.additional_includes.each do |inc|
119
+ includes << "#include \"#{inc}\""
120
+ end
121
+ end
122
+
123
+ # Set a list of user specified include files
124
+ def self.additional_includes=(addl)
125
+ @@additional_includes = addl
126
+ end
127
+
128
+ # Get an array of user specified include files
129
+ def self.additional_includes
130
+ @@additional_includes || []
131
+ end
132
+
133
+ # A list of all the source files. This is used in order to prevent files
134
+ # that are not in the list from being included and mucking things up
135
+ def self.sources=(sources)
136
+ @@sources = sources
137
+ end
138
+
139
+ # Retrieves a list of user specified source files
140
+ def self.sources
141
+ @@sources || []
57
142
  end
58
143
 
59
144
  # All builders must implement this method
@@ -64,7 +149,22 @@ module RbPlusPlus
64
149
  # Builders should use to_s to make finishing touches on the generated
65
150
  # code before it gets written out to a file.
66
151
  def to_s
67
- [self.includes.flatten.uniq, "", self.declarations, "", self.body].flatten.join("\n")
152
+ extras = []
153
+ #Weird trailing } needs to be destroyed!!!
154
+ if self.body.flatten[-1].strip == "}"
155
+ extras << self.body.delete_at(-1)
156
+ end
157
+
158
+ return [
159
+ self.includes.flatten.uniq,
160
+ "",
161
+ self.declarations,
162
+ "",
163
+ self.body,
164
+ "",
165
+ self.registered_nodes,
166
+ extras
167
+ ].flatten.join("\n")
68
168
  end
69
169
 
70
170
  # Get the full qualified name of the related gccxml node
@@ -73,25 +173,37 @@ module RbPlusPlus
73
173
  end
74
174
 
75
175
  # Register all classes
76
- def build_classes
77
- @node.classes.each do |klass|
176
+ def build_classes(classes = nil)
177
+ classes ||= [@node.classes, @node.structs].flatten
178
+ classes.each do |klass|
179
+ next if klass.ignored? || klass.moved?
180
+ next unless klass.public?
78
181
  builder = ClassBuilder.new(self, klass)
79
182
  builder.build
80
183
  builders << builder
81
184
  end
82
185
  end
83
186
 
187
+ # Find and wrap up all enumerations
188
+ def build_enumerations
189
+ @node.enumerations.each do |enum|
190
+ builder = EnumerationBuilder.new(self, enum)
191
+ builder.build
192
+ builders << builder
193
+ end
194
+ end
195
+
84
196
  # Compatibility with Rice 1.0.1's explicit self requirement, build a quick
85
197
  # wrapper that includes a self and discards it, forwarding the call as needed.
86
198
  #
87
199
  # Returns: the name of the wrapper function
88
- def build_function_wrapper(function)
89
- wrapper_func = "wrap_#{function.qualified_name.gsub(/::/, "_")}"
200
+ def build_function_wrapper(function, append="")
201
+ return if function.ignored? || function.moved?
202
+ wrapper_func = "wrap_#{function.qualified_name.gsub(/::/, "_")}#{append}"
90
203
 
91
204
  proto_string = ["Rice::Object self"]
92
205
  call_string = []
93
-
94
- function.arguments.map{|arg| [arg.cpp_type.name, arg.name]}.each do |parts|
206
+ function.arguments.map{|arg| [arg.cpp_type.to_s(true), arg.name]}.each do |parts|
95
207
  type = parts[0]
96
208
  name = parts[1]
97
209
  proto_string << "#{type} #{name}"
@@ -100,7 +212,7 @@ module RbPlusPlus
100
212
 
101
213
  proto_string = proto_string.join(",")
102
214
  call_string = call_string.join(",")
103
- return_type = function.return_type.name
215
+ return_type = function.return_type.to_s(true)
104
216
  returns = "" if return_type == "void"
105
217
  returns ||= "return"
106
218
 
@@ -111,6 +223,34 @@ module RbPlusPlus
111
223
  wrapper_func
112
224
  end
113
225
 
226
+ # Compatibility with Rice 1.0.1's method overloading issues. Build a quick
227
+ # wrapper that includes a self, forwarding the call as needed.
228
+ #
229
+ # Returns: the name of the wrapper function
230
+ def build_method_wrapper(cls, method, i)
231
+ return if method.ignored? || method.moved?
232
+ wrapper_func = "wrap_#{method.qualified_name.functionize}_#{i}"
233
+ proto_string = ["#{cls.qualified_name} *self"]
234
+ call_string = []
235
+ method.arguments.map{|arg| [arg.cpp_type.to_s(true), arg.name]}.each do |parts|
236
+ type = parts[0]
237
+ name = parts[1]
238
+ proto_string << "#{type} #{name}"
239
+ call_string << "#{name}"
240
+ end
241
+
242
+ proto_string = proto_string.join(",")
243
+ call_string = call_string.join(",")
244
+ return_type = method.return_type.to_s(true)
245
+ returns = "" if return_type == "void"
246
+ returns ||= "return"
247
+
248
+ declarations << "#{return_type} #{wrapper_func}(#{proto_string}) {"
249
+ declarations << "\t#{returns} self->#{method.qualified_name}(#{call_string});"
250
+ declarations << "}"
251
+
252
+ wrapper_func
253
+ end
114
254
  end
115
255
  end
116
256
  end
@@ -11,52 +11,127 @@ module RbPlusPlus
11
11
  end
12
12
 
13
13
  def build
14
- class_name = node.name
15
- full_name = node.qualified_name
16
- self.rice_variable = "rb_c#{class_name}"
17
- self.rice_variable_type = "Rice::Data_Type<#{full_name}>"
14
+
15
+ #Handles templated super classes
16
+ @typedef_name = node.qualified_name.functionize
17
+
18
+ #Handles templated super classes passing in complex members
19
+ var_name = node.name
20
+ var_name.gsub!("::","_")
21
+ var_name.gsub!(/[ ,<>]/, "_")
22
+ var_name.gsub!("*", "Ptr")
23
+
24
+ self.rice_variable = "rb_c#{var_name}"
25
+ self.rice_variable_type = "Rice::Data_Type<#{self.qualified_name} >"
18
26
 
19
27
  includes << "#include <rice/Class.hpp>"
20
28
  includes << "#include <rice/Data_Type.hpp>"
21
- includes << "#include <rice/Constructor.hpp>"
22
- includes << "#include \"#{node.file_name(false)}\""
29
+ includes << "#include <rice/Constructor.hpp>"
30
+
31
+ add_additional_includes
32
+ add_includes_for node
33
+
34
+ self.declarations.insert(0,"typedef #{node.qualified_name} #{@typedef_name};")
35
+
36
+ @body << class_definition
37
+
38
+ @body += constructors
39
+
40
+ @body += methods
23
41
 
24
- class_defn = "\t#{rice_variable_type} #{rice_variable} = "
25
- if !parent.is_a?(ExtensionBuilder)
26
- class_defn += "Rice::define_class_under<#{full_name}>(#{parent.rice_variable}, \"#{class_name}\");"
27
- else
28
- class_defn += "Rice::define_class<#{full_name}>(\"#{class_name}\");"
29
- end
42
+ # Nested Classes
43
+ build_classes
30
44
 
31
- body << class_defn
45
+ # Enumerations
46
+ build_enumerations
47
+ end
32
48
 
49
+ # Build the constructors, and return an array of rice code
50
+ def constructors
51
+ result = []
52
+ # There are no constructors on purely virtual classes.
53
+ node.methods.each do |method|
54
+ next unless method.is_a? RbGCCXML::Method
55
+ return [] if method.purely_virtual?
56
+ end
33
57
  # Constructors
34
58
  node.constructors.each do |init|
35
- args = [full_name, init.arguments.map {|a| a.cpp_type }].flatten
36
- body << "\t#{rice_variable}.define_constructor(Rice::Constructor<#{args.join(",")}>());"
59
+ next if init.ignored?
60
+ next unless init.public?
61
+ args = [@typedef_name, init.arguments.map {|a| a.cpp_type.to_s(true) }].flatten
62
+ result << "\t#{rice_variable}.define_constructor(Rice::Constructor<#{args.join(",")}>());"
37
63
  end
38
-
39
- # Methods
64
+ result
65
+ end
66
+
67
+ # Build the methods, and return an array of rice code
68
+ def methods
69
+ result = []
70
+ # Methods are thrown into a hash table so that we can
71
+ # determine overloaded methods
72
+ methods_hash = {}
40
73
  node.methods.each do |method|
41
- m = "define_method"
42
- name = method.qualified_name
43
-
44
- if method.static?
45
- m = "define_singleton_method"
46
- name = build_function_wrapper(method)
74
+ next unless method.public?
75
+
76
+ methods_hash[method.qualified_name] ||= []
77
+ methods_hash[method.qualified_name] << method
78
+ end
79
+
80
+ methods_hash.each do |key, methods|
81
+ #Add any method with a const return type to the typemanager
82
+ methods.each do |method|
83
+ next if method.ignored? || method.moved?
84
+ if method.return_type.const? || method.const?
85
+ TypesManager.build_const_converter(method.return_type)
86
+ end
47
87
  end
88
+ #No overloaded methods
89
+ if methods.length == 1
90
+ method = methods[0]
91
+ next if method.ignored? || method.moved?
92
+ m = "define_method"
93
+ name = method.qualified_name
48
94
 
49
- body << "\t#{rice_variable}.#{m}(\"#{Inflector.underscore(method.name)}\", &#{name});"
50
- end
95
+ if method.static?
96
+ m = "define_singleton_method"
97
+ name = build_function_wrapper(method)
98
+ end
51
99
 
52
- # Nested Classes
53
- node.classes.each do |klass|
54
- b = ClassBuilder.new(self, klass)
55
- b.build
56
- builders << b
100
+ result << "\t#{rice_variable}.#{m}(\"#{Inflector.underscore(method.name)}\", &#{name});"
101
+ else
102
+ #Handle overloaded methods
103
+ #currently we just append an index to them if they have not been renamed
104
+ #for example getOrigin() and getOrigin(x,y) become
105
+ #get_origin_0 and get_origin_1
106
+ methods.each_with_index do |method, i|
107
+ next if method.ignored? || method.moved?
108
+ name = build_method_wrapper(node, method, i)
109
+ m = "define_method"
110
+ method_name = "#{Inflector.underscore(method.name)}"
111
+ method_name += "_#{i}" unless method.renamed?
112
+ result << "\t#{rice_variable}.#{m}(\"#{method_name}\", &#{name});"
113
+ end
114
+ end
57
115
  end
116
+ result
117
+ end
118
+
119
+ # Return a rice string representing Rice's class definition.
120
+ def class_definition
121
+ class_defn = "\t#{rice_variable_type} #{rice_variable} = "
122
+
123
+ class_name = node.name
124
+ supers = node.super_classes.collect { |s| s.qualified_name }
125
+ class_names = [@typedef_name, supers].flatten.join(",")
126
+
127
+ if !parent.is_a?(ExtensionBuilder)
128
+ class_defn += "Rice::define_class_under<#{class_names} >(#{parent.rice_variable}, \"#{class_name}\");"
129
+ else
130
+ class_defn += "Rice::define_class<#{class_names} >(\"#{class_name}\");"
131
+ end
132
+ class_defn
58
133
  end
59
-
60
134
  end
135
+
61
136
  end
62
137
  end
@@ -0,0 +1,40 @@
1
+ module RbPlusPlus
2
+ module Builders
3
+
4
+ # This class handles generating source for a requested Module
5
+ class EnumerationBuilder < Base
6
+
7
+ # Different initializer to keep things clean
8
+ def initialize(parent, node)
9
+ super(node.name, node)
10
+ self.parent = parent
11
+ end
12
+
13
+ def build
14
+ includes << "#include <rice/Enum.hpp>"
15
+ enum_name = node.name
16
+ full_name = node.qualified_name
17
+ self.rice_variable = "rb_e#{enum_name}"
18
+ self.rice_variable_type = "Rice::Enum<#{full_name}>"
19
+
20
+ add_additional_includes
21
+
22
+ defn = "\t#{rice_variable_type} #{rice_variable} = "
23
+
24
+ second_arg = ""
25
+ if !parent.is_a?(ExtensionBuilder)
26
+ second_arg = ", #{parent.rice_variable}"
27
+ end
28
+
29
+ defn += "Rice::define_enum<#{full_name}>(\"#{enum_name}\" #{second_arg});"
30
+
31
+ body << defn
32
+
33
+ node.values.each do |v|
34
+ body << "\t#{rice_variable}.define_value(\"#{v.name}\", #{v.to_s(true)});"
35
+ end
36
+ end
37
+
38
+ end
39
+ end
40
+ end
@@ -11,17 +11,43 @@ module RbPlusPlus
11
11
  def build
12
12
  includes << "#include <rice/global_function.hpp>"
13
13
 
14
+ add_additional_includes
15
+
14
16
  body << "extern \"C\""
15
17
  body << "void Init_#{@name}() {"
16
18
 
17
19
  # Explicitly ignore anything from the :: namespace
18
20
  if @node.name != "::"
21
+
22
+ #Build a hash table to handle overloaded functions
23
+ func_hash = {}
19
24
  @node.functions.each do |func|
20
- includes << "#include \"#{func.file_name(false)}\""
21
- wrapper_name = build_function_wrapper(func)
22
- body << "\tdefine_global_function(\"#{Inflector.underscore(func.name)}\", &#{wrapper_name});"
25
+ next if func.ignored? || func.moved?
26
+
27
+ func_hash[func.name] ||= []
28
+ func_hash[func.name] << func
23
29
  end
30
+ #Iterate through the hash table to handle overloaded functions
31
+ func_hash.each do |key, funcs|
32
+ funcs.each_with_index do |func, i|
33
+ add_includes_for func
34
+
35
+ #append _#{i} to overloaded methods
36
+ #this needs to be done in both the wrapper function and the ruby function
37
+ func_append = ""
38
+ func_append = "_#{i}" if funcs.size > 1
39
+ wrapper_name = func.special_qualified_name || build_function_wrapper(func, func_append)
40
+
41
+ if func.return_type.const? || func.const?
42
+ TypesManager.build_const_converter(func.return_type)
43
+ end
24
44
 
45
+ ruby_name = "#{Inflector.underscore(func.name)}#{func_append}"
46
+ body << "\tdefine_global_function(\"#{ruby_name}\", &#{wrapper_name});"
47
+ end
48
+ end
49
+
50
+ build_enumerations
25
51
  build_classes
26
52
  end
27
53
 
@@ -39,9 +65,8 @@ module RbPlusPlus
39
65
  # Finish up the required code before doing final output
40
66
  def to_s
41
67
  includes << "using namespace Rice;"
42
- body << "}"
43
-
44
- super
68
+
69
+ super + "\n}"
45
70
  end
46
71
  end
47
72
  end
@@ -18,6 +18,8 @@ module RbPlusPlus
18
18
  self.rice_variable_type = "Rice::Module"
19
19
 
20
20
  includes << "#include <rice/Module.hpp>"
21
+
22
+ add_additional_includes
21
23
 
22
24
  mod_defn = "\t#{rice_variable_type} #{rice_variable} = "
23
25
  if !parent.is_a?(ExtensionBuilder)
@@ -29,11 +31,14 @@ module RbPlusPlus
29
31
  body << mod_defn
30
32
 
31
33
  # If a namespace has been given to this module, find and wrap the appropriate code
32
- if @node
33
- build_functions
34
- build_classes
34
+ if self.node
35
+ build_enumerations
35
36
  end
36
37
 
38
+ build_functions unless @module.functions.empty?
39
+ build_classes(@module.classes) unless @module.classes.empty?
40
+
41
+
37
42
  # Build each inner module
38
43
  @module.modules.each do |mod|
39
44
  builder = ModuleBuilder.new(self, mod)
@@ -44,11 +49,12 @@ module RbPlusPlus
44
49
 
45
50
  # Process functions to be added to this module
46
51
  def build_functions
47
- @node.functions.each do |func|
48
- includes << "#include \"#{func.file_name(false)}\""
52
+ @module.functions.each do |func|
53
+ next if func.ignored? || func.moved? # fine grained function filtering
54
+ add_includes_for func
49
55
 
50
56
  func_name = Inflector.underscore(func.name)
51
- wrapped_name = build_function_wrapper(func)
57
+ wrapped_name = func.special_qualified_name || build_function_wrapper(func)
52
58
  body << "\t#{self.rice_variable}.define_module_function(\"#{func_name}\", &#{wrapped_name});"
53
59
  end
54
60
  end