rbplusplus 0.1.1 → 0.8

Sign up to get free protection for your applications and to get access to all the features.
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