rbplusplus 0.1.1 → 0.8
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +31 -15
- data/TODO +20 -0
- data/lib/rbplusplus/builders/base.rb +148 -8
- data/lib/rbplusplus/builders/class.rb +106 -31
- data/lib/rbplusplus/builders/enumeration.rb +40 -0
- data/lib/rbplusplus/builders/extension.rb +31 -6
- data/lib/rbplusplus/builders/module.rb +12 -6
- data/lib/rbplusplus/builders/types_manager.rb +93 -0
- data/lib/rbplusplus/extension.rb +69 -41
- data/lib/rbplusplus/module.rb +3 -1
- data/lib/rbplusplus/transformers/class.rb +67 -0
- data/lib/rbplusplus/transformers/constructor.rb +4 -0
- data/lib/rbplusplus/transformers/function.rb +27 -0
- data/lib/rbplusplus/transformers/method.rb +4 -0
- data/lib/rbplusplus/transformers/module.rb +71 -0
- data/lib/rbplusplus/transformers/node.rb +77 -0
- data/lib/rbplusplus/transformers/node_cache.rb +19 -0
- data/lib/rbplusplus/transformers/node_reference.rb +30 -0
- data/lib/rbplusplus/transformers/rbgccxml.rb +6 -0
- data/lib/rbplusplus/writers/extension.rb +33 -25
- data/lib/rbplusplus/writers/multiple_files_writer.rb +42 -2
- data/lib/rbplusplus/writers/single_file_writer.rb +5 -0
- data/lib/rbplusplus.rb +24 -0
- data/test/class_methods_test.rb +55 -0
- data/test/classes_test.rb +0 -25
- data/test/compiling_test.rb +30 -0
- data/test/constructors_test.rb +40 -0
- data/test/enumerations_test.rb +63 -0
- data/test/file_writers_test.rb +56 -4
- data/test/generated/extconf.rb +25 -5
- data/test/headers/class_methods.h +41 -0
- data/test/headers/complex_static_methods.h +25 -0
- data/test/headers/constructors.h +47 -0
- data/test/headers/enums.h +77 -0
- data/test/headers/external_mapping.h +16 -0
- data/test/headers/external_mapping_rice.h +20 -0
- data/test/headers/include/helper.h +1 -0
- data/test/headers/nested_struct.h +20 -0
- data/test/headers/overload.h +28 -0
- data/test/headers/subclass.h +42 -0
- data/test/headers/to_from_ruby.h +78 -0
- data/test/headers/to_from_ruby_source.cpp +22 -0
- data/test/headers/ugly_helper.h +18 -0
- data/test/headers/ugly_interface.h +115 -0
- data/test/headers/ugly_interface_ns.h +8 -0
- data/test/nested_test.rb +26 -0
- data/test/object_persistence_test.rb +44 -0
- data/test/overloading_test.rb +36 -0
- data/test/struct_test.rb +22 -0
- data/test/subclass_test.rb +31 -0
- data/test/test_helper.rb +5 -0
- data/test/to_from_ruby_test.rb +24 -0
- data/test/wrap_as_test.rb +114 -0
- 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.
|
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
|
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"]
|
19
|
-
|
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
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
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.
|
61
|
-
s.add_dependency "rice", "1.0.
|
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
|
-
|
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.
|
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
|
-
|
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.
|
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
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
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
|
-
|
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
|
-
|
25
|
-
|
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
|
-
|
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
|
-
|
36
|
-
|
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
|
-
|
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
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
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
|
-
|
50
|
-
|
95
|
+
if method.static?
|
96
|
+
m = "define_singleton_method"
|
97
|
+
name = build_function_wrapper(method)
|
98
|
+
end
|
51
99
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
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
|
-
|
21
|
-
|
22
|
-
|
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
|
-
|
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
|
33
|
-
|
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
|
-
@
|
48
|
-
|
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
|