rbplusplus 0.8 → 0.9
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.
- data/Rakefile +13 -13
- data/TODO +9 -41
- data/lib/rbplusplus/builders/allocation_strategy.rb +57 -0
- data/lib/rbplusplus/builders/base.rb +115 -212
- data/lib/rbplusplus/builders/class.rb +129 -115
- data/lib/rbplusplus/builders/const.rb +30 -0
- data/lib/rbplusplus/builders/const_converter.rb +52 -0
- data/lib/rbplusplus/builders/constructor.rb +19 -0
- data/lib/rbplusplus/builders/director.rb +149 -0
- data/lib/rbplusplus/builders/director_method.rb +20 -0
- data/lib/rbplusplus/builders/enumeration.rb +19 -26
- data/lib/rbplusplus/builders/extension.rb +42 -54
- data/lib/rbplusplus/builders/global_function.rb +18 -0
- data/lib/rbplusplus/builders/helpers/class.rb +74 -0
- data/lib/rbplusplus/builders/helpers/enumeration.rb +28 -0
- data/lib/rbplusplus/builders/helpers/module.rb +22 -0
- data/lib/rbplusplus/builders/include.rb +32 -0
- data/lib/rbplusplus/builders/instance_variable.rb +36 -0
- data/lib/rbplusplus/builders/method.rb +14 -0
- data/lib/rbplusplus/builders/method_base.rb +136 -0
- data/lib/rbplusplus/builders/module.rb +37 -51
- data/lib/rbplusplus/builders/module_function.rb +16 -0
- data/lib/rbplusplus/builders/static_method.rb +14 -0
- data/lib/rbplusplus/extension.rb +140 -28
- data/lib/rbplusplus/logger.rb +45 -0
- data/lib/rbplusplus/module.rb +55 -1
- data/lib/rbplusplus/transformers/class.rb +116 -35
- data/lib/rbplusplus/transformers/function.rb +14 -16
- data/lib/rbplusplus/transformers/method.rb +26 -1
- data/lib/rbplusplus/transformers/namespace.rb +12 -0
- data/lib/rbplusplus/transformers/node.rb +47 -54
- data/lib/rbplusplus/transformers/node_cache.rb +5 -9
- data/lib/rbplusplus/writers/multiple_files_writer.rb +290 -88
- data/lib/rbplusplus/writers/single_file_writer.rb +36 -14
- data/lib/rbplusplus.rb +44 -18
- data/test/allocation_strategies_test.rb +33 -0
- data/test/class_methods_encapsulate_test.rb +59 -0
- data/test/class_methods_test.rb +2 -35
- data/test/classes_test.rb +72 -2
- data/test/compiling_test.rb +13 -0
- data/test/constructors_test.rb +9 -18
- data/test/custom_code_test.rb +53 -0
- data/test/default_arguments_test.rb +69 -0
- data/test/director_test.rb +173 -0
- data/test/enumerations_test.rb +29 -0
- data/test/extension_test.rb +7 -2
- data/test/file_writers_test.rb +11 -4
- data/test/function_pointer_test.rb +56 -0
- data/test/function_pointers_classes_test.rb +27 -0
- data/test/generated/extconf.rb +2 -2
- data/test/headers/Adder.cpp +8 -0
- data/test/headers/Adder.h +31 -1
- data/test/headers/alloc_strats.h +26 -0
- data/test/headers/class_methods.h +30 -0
- data/test/headers/code/custom_to_from_ruby.cpp +11 -0
- data/test/headers/code/custom_to_from_ruby.hpp +13 -0
- data/test/headers/constructors.h +8 -20
- data/test/headers/default_arguments.h +49 -0
- data/test/headers/director.h +148 -0
- data/test/headers/enums.h +33 -0
- data/test/headers/function_pointers.h +32 -0
- data/test/headers/function_pointers_class.h +26 -0
- data/test/headers/needs_code.h +10 -0
- data/test/headers/overload.h +0 -3
- data/test/headers/subclass.h +10 -0
- data/test/headers/to_from_ruby.h +6 -4
- data/test/headers/ugly_interface.h +4 -7
- data/test/modules_test.rb +11 -6
- data/test/overloading_test.rb +6 -2
- data/test/subclass_test.rb +20 -10
- data/test/test_helper.rb +6 -1
- data/test/to_from_ruby_test.rb +0 -2
- data/test/wrap_as_test.rb +28 -37
- metadata +89 -57
- data/lib/rbplusplus/builders/types_manager.rb +0 -93
- data/lib/rbplusplus/transformers/constructor.rb +0 -4
- data/lib/rbplusplus/transformers/module.rb +0 -71
- data/lib/rbplusplus/transformers/node_reference.rb +0 -30
- data/test/headers/ugly_helper.h +0 -18
- data/test/object_persistence_test.rb +0 -44
@@ -1,137 +1,151 @@
|
|
1
1
|
module RbPlusPlus
|
2
2
|
module Builders
|
3
3
|
|
4
|
-
#
|
5
|
-
class
|
4
|
+
# Handles the generation of Rice code to wrap classes
|
5
|
+
class ClassNode < Base
|
6
|
+
include ClassHelpers
|
7
|
+
include EnumerationHelpers
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
-
super(node.name, node)
|
10
|
-
self.parent = parent
|
9
|
+
def qualified_name
|
10
|
+
@qualified_name || self.code.qualified_name
|
11
11
|
end
|
12
12
|
|
13
13
|
def build
|
14
|
+
add_child IncludeNode.new(self, "rice/Class.hpp", :system)
|
15
|
+
add_child IncludeNode.new(self, "rice/Data_Type.hpp", :system)
|
16
|
+
add_child IncludeNode.new(self, code.file)
|
14
17
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
self.
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
#
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
18
|
+
typedef = find_typedef
|
19
|
+
|
20
|
+
@short_name, @qualified_name = typedef ? [typedef.name, typedef.qualified_name] : [code.name, code.qualified_name]
|
21
|
+
|
22
|
+
Logger.info "Wrapping class #{@qualified_name}"
|
23
|
+
|
24
|
+
@class_base_type = @qualified_name
|
25
|
+
|
26
|
+
supers = self.code.superclasses(:public)
|
27
|
+
@superclass = supers[0]
|
28
|
+
|
29
|
+
if supers.length > 1
|
30
|
+
if (@superclass = self.code._get_superclass).nil?
|
31
|
+
Logger.warn :mutiple_superclasses, "#{@qualified_name} has multiple public superclasses. " +
|
32
|
+
"Will use first superclass, which is #{supers[0].qualified_name} "
|
33
|
+
"Please use #use_superclass to specify another superclass as needed."
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
if self.code.needs_director?
|
38
|
+
@director = DirectorNode.new(self.code, self, @qualified_name, @superclass)
|
39
|
+
add_child @director
|
40
|
+
|
41
|
+
@qualified_name = @director.qualified_name
|
42
|
+
end
|
43
|
+
|
44
|
+
self.rice_variable = "rb_c#{@short_name.as_variable}"
|
45
|
+
self.rice_variable_type = "Rice::Data_Type< #{@qualified_name} >"
|
46
|
+
|
47
|
+
with_enumerations
|
48
|
+
with_classes
|
49
|
+
with_constructors
|
50
|
+
with_constants
|
51
|
+
with_variables
|
52
|
+
with_methods
|
53
|
+
|
54
|
+
unless @director
|
55
|
+
check_allocation_strategies
|
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)
|
47
61
|
end
|
48
62
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
63
|
+
def write
|
64
|
+
prefix = "#{rice_variable_type} #{rice_variable} = "
|
65
|
+
ruby_name = @short_name
|
66
|
+
expose_class = @qualified_name
|
67
|
+
superclass = @superclass.qualified_name if @superclass && !do_not_wrap?(@superclass)
|
68
|
+
|
69
|
+
if @director
|
70
|
+
@director.write_class_registration
|
71
|
+
expose_class = @director.qualified_name
|
72
|
+
superclass = @class_base_type
|
56
73
|
end
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
74
|
+
|
75
|
+
class_names = [expose_class]
|
76
|
+
class_names << superclass if superclass
|
77
|
+
class_names = class_names.join(",")
|
78
|
+
|
79
|
+
if parent.rice_variable
|
80
|
+
registrations << "#{prefix} Rice::define_class_under< #{class_names} >" +
|
81
|
+
"(#{parent.rice_variable}, \"#{ruby_name}\");"
|
82
|
+
else
|
83
|
+
registrations << "#{prefix} Rice::define_class< #{class_names} >(\"#{ruby_name}\");"
|
63
84
|
end
|
64
|
-
|
85
|
+
|
86
|
+
handle_custom_code
|
65
87
|
end
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
# Here we take the code manually added to the extension via #add_custom_code
|
92
|
+
def handle_custom_code
|
93
|
+
|
94
|
+
# Any declaration code, usually wrapper function definitions
|
95
|
+
self.code._get_custom_declarations.flatten.each do |decl|
|
96
|
+
declarations << decl
|
97
|
+
end
|
98
|
+
|
99
|
+
# And the registration code to hook into Rice
|
100
|
+
self.code._get_custom_wrappings.flatten.each do |wrap|
|
101
|
+
registrations << "#{wrap.gsub(/<class>/, self.rice_variable)}"
|
78
102
|
end
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
103
|
+
end
|
104
|
+
|
105
|
+
# We need to be sure to inform Rice of classes that may not have public
|
106
|
+
# constructors or destructors. This is because when a class is wrapped, code is generated
|
107
|
+
# to allocate the class directly. If this code tries to use a non-public
|
108
|
+
# constructor, we hit a compiler error.
|
109
|
+
def check_allocation_strategies
|
110
|
+
# Due to the nature of GCC-XML's handling of templated classes, there are some
|
111
|
+
# classes that might not have any gcc-generated constructors or destructors.
|
112
|
+
# We check here if we're one of those classes and completely skip this step
|
113
|
+
return if [self.code.constructors].flatten.empty?
|
114
|
+
|
115
|
+
# Find a public default constructor
|
116
|
+
found = [self.code.constructors.find(:arguments => [], :access => "public")].flatten
|
117
|
+
has_public_constructor = !found.empty?
|
118
|
+
|
119
|
+
# See if the destructor is public
|
120
|
+
has_public_destructor = self.code.destructor && self.code.destructor.public?
|
121
|
+
|
122
|
+
if !has_public_constructor || !has_public_destructor
|
123
|
+
add_global_child AllocationStrategyNode.new(self,
|
124
|
+
self.code, has_public_constructor, has_public_destructor)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
# Wrap up all public methods
|
129
|
+
def with_methods
|
130
|
+
method_names = @director ? @director.methods_wrapped.map {|m| m.name } : []
|
131
|
+
[self.code.methods].flatten.each do |method|
|
132
|
+
next if do_not_wrap?(method)
|
133
|
+
next if method_names.include?(method.name)
|
134
|
+
|
135
|
+
# Ignore methods that have non-public arguments anywhere
|
136
|
+
if !method.arguments.empty? && !method.arguments.select {|a| !a.cpp_type.base_type.public?}.empty?
|
137
|
+
Logger.info "Ignoring method #{method.qualified_name} due to non-public argument type(s)"
|
138
|
+
next
|
87
139
|
end
|
88
|
-
|
89
|
-
if
|
90
|
-
method
|
91
|
-
next if method.ignored? || method.moved?
|
92
|
-
m = "define_method"
|
93
|
-
name = method.qualified_name
|
94
|
-
|
95
|
-
if method.static?
|
96
|
-
m = "define_singleton_method"
|
97
|
-
name = build_function_wrapper(method)
|
98
|
-
end
|
99
|
-
|
100
|
-
result << "\t#{rice_variable}.#{m}(\"#{Inflector.underscore(method.name)}\", &#{name});"
|
140
|
+
|
141
|
+
if method.static?
|
142
|
+
add_child StaticMethodNode.new(method, self)
|
101
143
|
else
|
102
|
-
|
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
|
144
|
+
add_child MethodNode.new(method, self)
|
114
145
|
end
|
115
146
|
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
|
133
147
|
end
|
148
|
+
|
134
149
|
end
|
135
|
-
|
136
150
|
end
|
137
151
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module RbPlusPlus
|
2
|
+
module Builders
|
3
|
+
|
4
|
+
# Expose a const value
|
5
|
+
class ConstNode < Base
|
6
|
+
|
7
|
+
def build
|
8
|
+
add_child IncludeNode.new(self, code.file)
|
9
|
+
end
|
10
|
+
|
11
|
+
def write
|
12
|
+
# If this constant is initialized in the header, we need to set the constant to the initialized value
|
13
|
+
# If we just use the variable itself, Linux will fail to compile because the linker won't be able to
|
14
|
+
# find the constant.
|
15
|
+
set_to =
|
16
|
+
if init = code.attributes["init"]
|
17
|
+
init
|
18
|
+
else
|
19
|
+
code.qualified_name
|
20
|
+
end
|
21
|
+
|
22
|
+
prefix = parent.rice_variable ? "#{parent.rice_variable}." : "Rice::Module(rb_mKernel)."
|
23
|
+
registrations << "#{prefix}const_set(\"#{code.name}\", to_ruby(#{set_to}));"
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module RbPlusPlus
|
2
|
+
module Builders
|
3
|
+
|
4
|
+
# Handles code generation for to_ruby converters for const& types
|
5
|
+
class ConstConverterNode < Base
|
6
|
+
|
7
|
+
# Used by MultipleFileWriter to only wrap a given type once.
|
8
|
+
def qualified_name
|
9
|
+
"#{self.code.qualified_name}_ConstConverter"
|
10
|
+
end
|
11
|
+
|
12
|
+
def build
|
13
|
+
Logger.debug("Building const converter for #{self.code.qualified_name}")
|
14
|
+
end
|
15
|
+
|
16
|
+
def write
|
17
|
+
full_name = self.code.qualified_name
|
18
|
+
|
19
|
+
# Various reasons we don't want to generate this:
|
20
|
+
# Rice already handles it
|
21
|
+
if full_name =~ /std::string/
|
22
|
+
Logger.debug("Not building const converter for #{full_name}")
|
23
|
+
return
|
24
|
+
end
|
25
|
+
|
26
|
+
Logger.debug("Writing out const converter for #{full_name}")
|
27
|
+
|
28
|
+
includes << "#include <rice/Object.hpp>"
|
29
|
+
includes << "#include <rice/Data_Object.hpp>"
|
30
|
+
includes << "#include <rice/Data_Type.hpp>"
|
31
|
+
|
32
|
+
includes << "#include \"#{self.code.file}\""
|
33
|
+
|
34
|
+
declarations << "template<>"
|
35
|
+
declarations << "Rice::Object to_ruby<#{full_name} >(#{full_name} const & a);"
|
36
|
+
|
37
|
+
build_as = if self.parent.is_a?(EnumerationNode)
|
38
|
+
"new #{full_name}(a)"
|
39
|
+
else
|
40
|
+
"(#{full_name} *)&a"
|
41
|
+
end
|
42
|
+
|
43
|
+
registrations << "template<>"
|
44
|
+
registrations << "Rice::Object to_ruby<#{full_name} >(#{full_name} const & a) {"
|
45
|
+
registrations << "\treturn Rice::Data_Object<#{full_name} >(#{build_as}, Rice::Data_Type<#{full_name} >::klass(), 0, 0);"
|
46
|
+
registrations << "}"
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module RbPlusPlus
|
2
|
+
module Builders
|
3
|
+
|
4
|
+
# Wrap class constructor(s)
|
5
|
+
class ConstructorNode < Base
|
6
|
+
|
7
|
+
def build
|
8
|
+
add_child IncludeNode.new(self, "rice/Constructor.hpp", :system)
|
9
|
+
end
|
10
|
+
|
11
|
+
def write
|
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(",")} >());"
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
module RbPlusPlus
|
2
|
+
module Builders
|
3
|
+
|
4
|
+
# This class takes care of the generation of Rice::Director wrapper
|
5
|
+
# classes. It's slightly different than other nodes, as it's self.code
|
6
|
+
# is the class we're wrapping a director around.
|
7
|
+
class DirectorNode < Base
|
8
|
+
|
9
|
+
attr_reader :methods_wrapped
|
10
|
+
|
11
|
+
def initialize(code, parent, class_qualified_name, superclass)
|
12
|
+
super(code, parent)
|
13
|
+
|
14
|
+
@class_qualified_name = class_qualified_name
|
15
|
+
@methods_wrapped = []
|
16
|
+
@superclass = superclass
|
17
|
+
@constructors = []
|
18
|
+
|
19
|
+
@class_base_name = class_qualified_name.split("::")[-1]
|
20
|
+
@name = "#{@class_base_name}Director"
|
21
|
+
end
|
22
|
+
|
23
|
+
def qualified_name
|
24
|
+
@name
|
25
|
+
end
|
26
|
+
|
27
|
+
def build
|
28
|
+
add_child IncludeNode.new(self, "rice/Director.hpp", :global)
|
29
|
+
add_child IncludeNode.new(self, "rice/Constructor.hpp", :global)
|
30
|
+
|
31
|
+
# To ensure proper compilation, this director class needs
|
32
|
+
# to implement all pure virtual methods found up the
|
33
|
+
# inheritance heirarchy of this class. So here, we traverse
|
34
|
+
# this list and build the nest of required methods
|
35
|
+
wrapped_names = []
|
36
|
+
klass = self.code
|
37
|
+
while klass.is_a?(RbGCCXML::Class) || klass.is_a?(RbGCCXML::Struct)
|
38
|
+
[klass.methods].flatten.each do |method|
|
39
|
+
next if do_not_wrap?(method)
|
40
|
+
if method.virtual? && !wrapped_names.include?(method.name)
|
41
|
+
@methods_wrapped << method
|
42
|
+
wrapped_names << method.name
|
43
|
+
|
44
|
+
add_child DirectorMethodNode.new(method, self.parent, self)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
klass = klass.superclass
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def wrap_constructor(constructor)
|
52
|
+
@constructors << constructor
|
53
|
+
end
|
54
|
+
|
55
|
+
def write_class_registration
|
56
|
+
# Need to tell Rice of the base class, while also making sure that if there's a superclass to this class
|
57
|
+
# that we know about it, or attempts to use polymorphism will crash with 'unknown caster for {superclass}
|
58
|
+
class_names = [@class_qualified_name]
|
59
|
+
class_names << @superclass.qualified_name if @superclass && !do_not_wrap?(@superclass)
|
60
|
+
class_names = class_names.join(",")
|
61
|
+
|
62
|
+
self.parent.registrations << "Rice::define_class< #{class_names} >(\"__#{@class_base_name}__\");"
|
63
|
+
end
|
64
|
+
|
65
|
+
def write_constructor(constructor = nil)
|
66
|
+
args = ["Rice::Object self"]
|
67
|
+
types = [@name, "Rice::Object"]
|
68
|
+
supercall_args = []
|
69
|
+
|
70
|
+
if constructor
|
71
|
+
constructor.arguments.each do |arg|
|
72
|
+
type = arg.cpp_type.to_cpp
|
73
|
+
name = arg.name
|
74
|
+
|
75
|
+
args << "#{type} #{name}"
|
76
|
+
types << type
|
77
|
+
supercall_args << name
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
declarations << "#{@name}(#{args.join(", ")}) : #{@class_qualified_name}(#{supercall_args.join(", ")}), Rice::Director(self) { }"
|
82
|
+
registrations << "#{self.parent.rice_variable}.define_constructor(Rice::Constructor< #{types.join(", ")} >());"
|
83
|
+
end
|
84
|
+
|
85
|
+
def write
|
86
|
+
declarations << "class #{@name} : public #{@class_qualified_name}, public Rice::Director {"
|
87
|
+
declarations << "public:"
|
88
|
+
|
89
|
+
# Handle constructors
|
90
|
+
if @constructors.empty?
|
91
|
+
write_constructor
|
92
|
+
else
|
93
|
+
@constructors.each {|c| write_constructor(c) }
|
94
|
+
end
|
95
|
+
|
96
|
+
# Each virtual method gets wrapped
|
97
|
+
@methods_wrapped.each do |method|
|
98
|
+
|
99
|
+
cpp_name = method.qualified_name.split("::")[-1]
|
100
|
+
ruby_name = Inflector.underscore(method.name)
|
101
|
+
return_type = method.return_type.to_cpp
|
102
|
+
return_call = return_type != "void" ? "return" : ""
|
103
|
+
|
104
|
+
def_arguments = []
|
105
|
+
call_arguments = []
|
106
|
+
method.arguments.each do |a|
|
107
|
+
def_arg = a.value ? " = #{a.value}" : ""
|
108
|
+
def_arguments << "#{a.cpp_type.to_cpp} #{a.name}#{def_arg}"
|
109
|
+
call_arguments << a.name
|
110
|
+
end
|
111
|
+
|
112
|
+
def_arguments = def_arguments.length == 0 ? "" : def_arguments.join(", ")
|
113
|
+
|
114
|
+
reverse = ""
|
115
|
+
up_or_raise =
|
116
|
+
if method.default_return_value
|
117
|
+
reverse = "!"
|
118
|
+
"return #{method.default_return_value};"
|
119
|
+
else
|
120
|
+
if method.purely_virtual?
|
121
|
+
"raisePureVirtual()"
|
122
|
+
else
|
123
|
+
"#{return_call} this->#{method.qualified_name}(#{call_arguments.join(", ")})"
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
call_down = "getSelf().call(\"#{ruby_name}\"#{call_arguments.empty? ? "" : ", "}#{call_arguments.map {|a| "to_ruby(#{a})" }.join(", ")})"
|
128
|
+
call_down = "return from_ruby< #{return_type} >( #{call_down} )" if return_type != "void"
|
129
|
+
|
130
|
+
const = method.const? ? "const" : ""
|
131
|
+
|
132
|
+
declarations << ""
|
133
|
+
declarations << "#{return_type} #{cpp_name}(#{def_arguments}) #{const} {"
|
134
|
+
declarations << "if(#{reverse}callIsFromRuby(\"#{ruby_name}\")) {"
|
135
|
+
declarations << "#{up_or_raise};"
|
136
|
+
declarations << "} else {"
|
137
|
+
declarations << "#{call_down};"
|
138
|
+
declarations << "}"
|
139
|
+
declarations << "}"
|
140
|
+
end
|
141
|
+
|
142
|
+
declarations << "};"
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module RbPlusPlus
|
2
|
+
module Builders
|
3
|
+
|
4
|
+
# Expose a director method as an instance method
|
5
|
+
class DirectorMethodNode < MethodNode
|
6
|
+
|
7
|
+
def initialize(method, parent, director)
|
8
|
+
super(method, parent)
|
9
|
+
@director = director
|
10
|
+
end
|
11
|
+
|
12
|
+
def code_path
|
13
|
+
cpp_name = self.code.qualified_name.split("::")[-1]
|
14
|
+
"#{@director.qualified_name}::#{cpp_name}"
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -1,37 +1,30 @@
|
|
1
1
|
module RbPlusPlus
|
2
2
|
module Builders
|
3
3
|
|
4
|
-
#
|
5
|
-
class
|
6
|
-
|
7
|
-
# Different initializer to keep things clean
|
8
|
-
def initialize(parent, node)
|
9
|
-
super(node.name, node)
|
10
|
-
self.parent = parent
|
11
|
-
end
|
4
|
+
# Expose an enumeration.
|
5
|
+
class EnumerationNode < Base
|
12
6
|
|
13
7
|
def build
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
self.
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
if !parent.is_a?(ExtensionBuilder)
|
26
|
-
second_arg = ", #{parent.rice_variable}"
|
27
|
-
end
|
8
|
+
add_child IncludeNode.new(self, "rice/Enum.hpp", :system)
|
9
|
+
add_child IncludeNode.new(self, code.file)
|
10
|
+
|
11
|
+
# See ClassNode
|
12
|
+
add_global_child ConstConverterNode.new(self.code, self)
|
13
|
+
|
14
|
+
self.rice_variable_type = "Rice::Enum<#{code.qualified_name}>"
|
15
|
+
self.rice_variable = "rb_e#{code.name}"
|
16
|
+
|
17
|
+
Logger.info "Wrapping enumeration #{code.qualified_name}"
|
18
|
+
end
|
28
19
|
|
29
|
-
|
20
|
+
def write
|
21
|
+
second = parent.rice_variable ? ", #{parent.rice_variable}" : ""
|
30
22
|
|
31
|
-
|
23
|
+
registrations << "#{rice_variable_type} #{rice_variable} = " \
|
24
|
+
"Rice::define_enum<#{code.qualified_name}>(\"#{code.name}\"#{second});"
|
32
25
|
|
33
|
-
|
34
|
-
|
26
|
+
code.values.each do |v|
|
27
|
+
registrations << "#{rice_variable}.define_value(\"#{v.name}\", #{v.qualified_name});"
|
35
28
|
end
|
36
29
|
end
|
37
30
|
|