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