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.
- 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
@@ -6,38 +6,46 @@ module RbPlusPlus
|
|
6
6
|
# file with the appropriate options.
|
7
7
|
class ExtensionWriter < Base
|
8
8
|
|
9
|
-
#
|
10
|
-
attr_accessor :
|
9
|
+
# Options given from the extension
|
10
|
+
attr_accessor :options
|
11
11
|
|
12
|
-
|
13
|
-
|
12
|
+
def write
|
13
|
+
extconf = File.join(working_dir, "extconf.rb")
|
14
14
|
|
15
|
-
|
16
|
-
|
15
|
+
inc_str = @options[:include_paths].flatten.uniq.map {|i| "-I#{i}"}.join(" ")
|
16
|
+
inc_str += " " + @options[:cxxflags].flatten.join(" ")
|
17
|
+
lib_path_str = @options[:library_paths].flatten.uniq.map {|i| "-L#{i}"}.join(" ")
|
18
|
+
lib_str = @options[:libraries].flatten.uniq.map {|i| "-l#{i}"}.join(" ")
|
19
|
+
lib_str += " " + @options[:ldflags].flatten.join(" ")
|
17
20
|
|
18
|
-
|
19
|
-
|
21
|
+
File.open(extconf, "w+") do |file|
|
22
|
+
file.puts <<-EOF
|
23
|
+
require 'rubygems'
|
24
|
+
require 'mkmf-rice'
|
25
|
+
|
26
|
+
# Add the arguments to the linker flags.
|
27
|
+
def append_ld_flags(flags)
|
28
|
+
flags = [flags] unless flags.is_a?(Array)
|
29
|
+
with_ldflags("\#{$LDFLAGS} \#{flags.join(' ')}") { true }
|
30
|
+
end
|
20
31
|
|
21
|
-
|
22
|
-
|
32
|
+
$CPPFLAGS += \" -I'#{working_dir}' #{inc_str}\"
|
33
|
+
$LDFLAGS += \" #{lib_path_str} #{lib_str}\"
|
23
34
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
35
|
+
if RUBY_PLATFORM =~ /darwin/
|
36
|
+
# In order to link the shared library into our bundle with GCC 4.x on OSX, we have to work around a bug:
|
37
|
+
# GCC redefines symbols - which the -fno-common prohibits. In order to keep the -fno-common, we
|
38
|
+
# remove the flat_namespace (we now have two namespaces, which fixes the GCC clash). Also, we now lookup
|
39
|
+
# symbols in both the namespaces (dynamic_lookup).
|
28
40
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
41
|
+
$LDSHARED_CXX.gsub!('suppress', 'dynamic_lookup')
|
42
|
+
$LDSHARED_CXX.gsub!('-flat_namespace', '')
|
43
|
+
|
44
|
+
append_ld_flags '-all_load'
|
45
|
+
end
|
34
46
|
|
35
|
-
|
36
|
-
|
37
|
-
file.puts "require \"mkmf-rice\""
|
38
|
-
file.puts %Q($CPPFLAGS = $CPPFLAGS + " -I#{working_dir} #{inc_str}")
|
39
|
-
file.puts %Q($LDFLAGS = $LDFLAGS + " #{lib_path_str} #{lib_str}")
|
40
|
-
file.puts "create_makefile(\"#{builder.name}\")"
|
47
|
+
create_makefile(\"#{builder.name}\")
|
48
|
+
EOF
|
41
49
|
end
|
42
50
|
end
|
43
51
|
|
@@ -5,9 +5,41 @@ module RbPlusPlus
|
|
5
5
|
class MultipleFilesWriter < Base
|
6
6
|
|
7
7
|
def write
|
8
|
+
@to_from_include = ""
|
9
|
+
write_to_from_ruby
|
8
10
|
_write_node(builder)
|
9
11
|
end
|
10
12
|
|
13
|
+
# Write out files that include the auto-generated to_/from_ruby constructs.
|
14
|
+
def write_to_from_ruby
|
15
|
+
# Ignore this if there's nothing to write out
|
16
|
+
return if Builders::TypesManager.body.length == 0
|
17
|
+
|
18
|
+
hpp_file = File.join(working_dir, "_to_from_ruby.rb.hpp")
|
19
|
+
cpp_file = File.join(working_dir, "_to_from_ruby.rb.cpp")
|
20
|
+
|
21
|
+
@to_from_include = "#include \"#{hpp_file}\""
|
22
|
+
|
23
|
+
include_guard = "__RICE_GENERATED_TO_FROM_RUBY_HPP__"
|
24
|
+
|
25
|
+
File.open(hpp_file, "w+") do |f|
|
26
|
+
f.puts "#ifndef #{include_guard}"
|
27
|
+
f.puts "#define #{include_guard}"
|
28
|
+
f.puts ""
|
29
|
+
f.puts Builders::TypesManager.includes.uniq.join("\n")
|
30
|
+
f.puts ""
|
31
|
+
f.puts Builders::TypesManager.prototypes.join("\n")
|
32
|
+
f.puts ""
|
33
|
+
f.puts "#endif // #{include_guard}"
|
34
|
+
end
|
35
|
+
|
36
|
+
File.open(cpp_file, "w+") do |f|
|
37
|
+
f.puts @to_from_include
|
38
|
+
f.puts ""
|
39
|
+
f.puts Builders::TypesManager.body.join("\n");
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
11
43
|
# How this works:
|
12
44
|
#
|
13
45
|
# We'll recurse through the builder heirarchy, starting at the bottom.
|
@@ -19,10 +51,15 @@ module RbPlusPlus
|
|
19
51
|
end
|
20
52
|
|
21
53
|
filename = if node.parent
|
22
|
-
node.qualified_name.gsub(/::/, "_")
|
54
|
+
"_"+node.qualified_name.gsub(/::/, "_")
|
23
55
|
else
|
24
56
|
node.name
|
25
57
|
end
|
58
|
+
|
59
|
+
#templated classes
|
60
|
+
filename.gsub!(/[ ,<>]/,"_")
|
61
|
+
#templates to pointers
|
62
|
+
filename.gsub!("*","Ptr")
|
26
63
|
|
27
64
|
cpp_file = File.join(working_dir, "#{filename}.rb.cpp")
|
28
65
|
|
@@ -48,7 +85,8 @@ module RbPlusPlus
|
|
48
85
|
# * Add a call to the register method
|
49
86
|
node.parent.includes << hpp_include
|
50
87
|
|
51
|
-
|
88
|
+
# Register for proper flattening of the inheritance tree
|
89
|
+
node.parent.register_node(node, "#{register_func}(#{register_func_arg});")
|
52
90
|
|
53
91
|
# Modifications to this current node's code:
|
54
92
|
#
|
@@ -60,6 +98,8 @@ module RbPlusPlus
|
|
60
98
|
hpp.puts "#ifndef #{include_guard}"
|
61
99
|
hpp.puts "#define #{include_guard}"
|
62
100
|
hpp.puts ""
|
101
|
+
hpp.puts @to_from_include
|
102
|
+
hpp.puts ""
|
63
103
|
hpp.puts "void #{register_func}(#{register_func_prototype});"
|
64
104
|
hpp.puts "#endif"
|
65
105
|
end
|
@@ -7,6 +7,11 @@ module RbPlusPlus
|
|
7
7
|
def write
|
8
8
|
process_code(builder)
|
9
9
|
|
10
|
+
if Builders::TypesManager.body.length > 0
|
11
|
+
# Handle to_from_ruby constructions
|
12
|
+
builder.declarations << Builders::TypesManager.body
|
13
|
+
end
|
14
|
+
|
10
15
|
filename = builder.name
|
11
16
|
cpp_file = File.join(working_dir, "#{filename}.rb.cpp")
|
12
17
|
|
data/lib/rbplusplus.rb
CHANGED
@@ -6,8 +6,11 @@ require 'rbgccxml'
|
|
6
6
|
|
7
7
|
require 'inflector'
|
8
8
|
require 'fileutils'
|
9
|
+
require 'singleton'
|
9
10
|
require 'rbplusplus/rbplusplus'
|
10
11
|
|
12
|
+
require 'fileutils'
|
13
|
+
|
11
14
|
module RbPlusPlus
|
12
15
|
|
13
16
|
RBPP_COMMENT = "// This file generated by rb++"
|
@@ -20,6 +23,8 @@ module RbPlusPlus
|
|
20
23
|
autoload :ClassBuilder, "rbplusplus/builders/class"
|
21
24
|
autoload :ExtensionBuilder, "rbplusplus/builders/extension"
|
22
25
|
autoload :ModuleBuilder, "rbplusplus/builders/module"
|
26
|
+
autoload :EnumerationBuilder, "rbplusplus/builders/enumeration"
|
27
|
+
autoload :TypesManager, "rbplusplus/builders/types_manager"
|
23
28
|
end
|
24
29
|
|
25
30
|
module Writers
|
@@ -30,3 +35,22 @@ module RbPlusPlus
|
|
30
35
|
end
|
31
36
|
end
|
32
37
|
|
38
|
+
class String #:nodoc:
|
39
|
+
# Functionize attempts to rename a string in a cpp function friendly way.
|
40
|
+
#
|
41
|
+
# vector<float>::x => vector_float__x
|
42
|
+
def functionize
|
43
|
+
gsub("::","_").gsub(/[ ,<>]/, "_").gsub("*", "Ptr")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
require 'rbplusplus/transformers/rbgccxml'
|
48
|
+
require 'rbplusplus/transformers/node_cache'
|
49
|
+
require 'rbplusplus/transformers/node'
|
50
|
+
require 'rbplusplus/transformers/node_reference'
|
51
|
+
require 'rbplusplus/transformers/function'
|
52
|
+
require 'rbplusplus/transformers/method'
|
53
|
+
require 'rbplusplus/transformers/constructor'
|
54
|
+
require 'rbplusplus/transformers/class'
|
55
|
+
require 'rbplusplus/transformers/module'
|
56
|
+
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
context "Correct handling of static methods" do
|
4
|
+
def setup
|
5
|
+
if !defined?(@@complex_static)
|
6
|
+
super
|
7
|
+
@@complex_static = true
|
8
|
+
Extension.new "complex" do |e|
|
9
|
+
e.sources full_dir("headers/complex_static_methods.h")
|
10
|
+
node = e.namespace "complex"
|
11
|
+
end
|
12
|
+
|
13
|
+
require 'complex'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
specify "should handle complex static methods" do
|
18
|
+
Multiply.multiply(SmallInteger.new(2),SmallInteger.new(2)).should == 4
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
context "Correct handling of encapsulated methods" do
|
24
|
+
def setup
|
25
|
+
if !defined?(@@encapsulated)
|
26
|
+
super
|
27
|
+
@@encapsulated = true
|
28
|
+
Extension.new "encapsulation" do |e|
|
29
|
+
e.sources full_dir("headers/class_methods.h")
|
30
|
+
node = e.namespace "encapsulation"
|
31
|
+
end
|
32
|
+
|
33
|
+
require 'encapsulation'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
specify "should handle private/protected/public" do
|
38
|
+
ext = Extended.new
|
39
|
+
ext.public_method.should == 1
|
40
|
+
should.raise NoMethodError do
|
41
|
+
ext.private_method
|
42
|
+
end
|
43
|
+
should.raise NoMethodError do
|
44
|
+
ext.protected_method
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
specify "should handle virtual methods" do
|
49
|
+
ext_factory = ExtendedFactory.new
|
50
|
+
ext = ext_factory.new_instance
|
51
|
+
ext.fundamental_type_virtual_method.should == 1
|
52
|
+
ext.user_defined_type_virtual_method.class.should == Base
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
data/test/classes_test.rb
CHANGED
@@ -40,28 +40,3 @@ context "Extension with wrapped classes" do
|
|
40
40
|
|
41
41
|
end
|
42
42
|
|
43
|
-
context "Wrapping Classes within classes" do
|
44
|
-
|
45
|
-
def setup
|
46
|
-
if !defined?(@@nested_built)
|
47
|
-
super
|
48
|
-
@@nested_built = true
|
49
|
-
Extension.new "nested" do |e|
|
50
|
-
e.sources full_dir("headers/nested_classes.h")
|
51
|
-
e.namespace "classes"
|
52
|
-
end
|
53
|
-
|
54
|
-
require 'nested'
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
specify "should properly make nested classes available" do
|
59
|
-
assert defined?(TestClass)
|
60
|
-
assert defined?(TestClass::InnerClass)
|
61
|
-
assert defined?(TestClass::InnerClass::Inner2)
|
62
|
-
|
63
|
-
TestClass.new.should.not.be.nil
|
64
|
-
TestClass::InnerClass.new.should.not.be.nil
|
65
|
-
TestClass::InnerClass::Inner2.new.should.not.be.nil
|
66
|
-
end
|
67
|
-
end
|
data/test/compiling_test.rb
CHANGED
@@ -126,4 +126,34 @@ context "Compiler settings" do
|
|
126
126
|
e.write
|
127
127
|
end
|
128
128
|
end
|
129
|
+
|
130
|
+
specify "should be able to add additional headers as needed" do
|
131
|
+
should.not.raise do
|
132
|
+
e = Extension.new "external"
|
133
|
+
e.working_dir = full_dir("generated")
|
134
|
+
e.sources full_dir("headers/external_mapping.h"),
|
135
|
+
:includes => full_dir("headers/*rice.h")
|
136
|
+
e.build
|
137
|
+
e.write
|
138
|
+
|
139
|
+
file = full_dir("generated/external.rb.cpp")
|
140
|
+
contents = File.read(file)
|
141
|
+
contents.should.match(%r(headers/external_mapping_rice.h))
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
specify "can specify other source files to be compiled into the extension" do
|
146
|
+
Extension.new "source_files" do |e|
|
147
|
+
e.sources full_dir("headers/to_from_ruby.h"),
|
148
|
+
:include_paths => full_dir("headers"),
|
149
|
+
:include_source_files => full_dir("headers/to_from_ruby_source.cpp")
|
150
|
+
e.namespace "to_from_ruby"
|
151
|
+
end
|
152
|
+
|
153
|
+
require 'source_files'
|
154
|
+
|
155
|
+
# Don't know if there's any way to catch this nicely. A failure here
|
156
|
+
# is a symbol lookup failure and death to the Ruby VM
|
157
|
+
needs_to_ruby(3).value.should == 3
|
158
|
+
end
|
129
159
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
context "Extension with constructors out the whazoo" do
|
4
|
+
|
5
|
+
# Test is currently broken due to something Rice is or isn't doing.
|
6
|
+
xspecify "should make constructors available" do
|
7
|
+
Extension.new "constructors" do |e|
|
8
|
+
e.sources full_dir("headers/constructors.h")
|
9
|
+
node = e.namespace "constructors"
|
10
|
+
e.writer_mode :single
|
11
|
+
end
|
12
|
+
|
13
|
+
require 'constructors'
|
14
|
+
|
15
|
+
should.not.raise NameError do
|
16
|
+
# Constructor overloading not yet supported
|
17
|
+
# s = StringHolder.new
|
18
|
+
# s.set_name "two"
|
19
|
+
# s.get_name.should == "two"
|
20
|
+
|
21
|
+
s2 = StringHolder.new "one"
|
22
|
+
s2.get_name.should == "one"
|
23
|
+
end
|
24
|
+
|
25
|
+
should.not.raise NameError do
|
26
|
+
# Test complex constructors
|
27
|
+
d = DoubleStringHolder.new(StringHolder.new("one"), StringHolder.new("two"))
|
28
|
+
one = d.get_one
|
29
|
+
puts "Got one #{one.inspect}"
|
30
|
+
puts "Name is #{one.get_name}"
|
31
|
+
# d.get_one.get_name.should == "one"
|
32
|
+
# d.get_two.get_name.should == "two"
|
33
|
+
end
|
34
|
+
|
35
|
+
should.raise TypeError do
|
36
|
+
PrivateConstructor.new
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
context "Wrapping enumerations" do
|
4
|
+
|
5
|
+
def setup
|
6
|
+
if !defined?(@@enums_built)
|
7
|
+
super
|
8
|
+
@@enums_built = true
|
9
|
+
Extension.new "enums" do |e|
|
10
|
+
e.sources full_dir("headers/enums.h")
|
11
|
+
e.namespace "enums"
|
12
|
+
e.writer_mode :single
|
13
|
+
|
14
|
+
e.module "Mod" do |m|
|
15
|
+
m.namespace "inner"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
require 'enums'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
specify "should wrap up enums properly" do
|
24
|
+
assert defined?(TestEnum)
|
25
|
+
|
26
|
+
TestEnum::VALUE1.to_i.should == 0
|
27
|
+
TestEnum::VALUE2.to_i.should == 1
|
28
|
+
TestEnum::VALUE3.to_i.should == 2
|
29
|
+
end
|
30
|
+
|
31
|
+
specify "should wrap up enumerations at proper nesting" do
|
32
|
+
assert defined?(Tester::MyEnum)
|
33
|
+
|
34
|
+
Tester::MyEnum::I_LIKE_MONEY.to_i.should == 3
|
35
|
+
Tester::MyEnum::YOU_LIKE_MONEY_TOO.to_i.should == 4
|
36
|
+
Tester::MyEnum::I_LIKE_YOU.to_i.should == 7
|
37
|
+
end
|
38
|
+
|
39
|
+
specify "should work in user-defined modules" do
|
40
|
+
assert defined?(Mod::InnerEnum)
|
41
|
+
|
42
|
+
Mod::InnerEnum::INNER_1.to_i.should == 0
|
43
|
+
Mod::InnerEnum::INNER_2.to_i.should == 1
|
44
|
+
end
|
45
|
+
|
46
|
+
specify "should allow use of enumerations as types" do
|
47
|
+
what_test_enum(TestEnum::VALUE1).should == "We gots enum 0";
|
48
|
+
|
49
|
+
# Types should be adhered to
|
50
|
+
should.raise RuntimeError do
|
51
|
+
what_test_enum(Mod::InnerEnum::INNER_1)
|
52
|
+
end
|
53
|
+
|
54
|
+
t = Tester.new
|
55
|
+
t.get_enum_description(Tester::MyEnum::YOU_LIKE_MONEY_TOO).should == "You like money!"
|
56
|
+
end
|
57
|
+
|
58
|
+
specify "should properly build to_ruby converters for const enum return types" do
|
59
|
+
t = Tester.new
|
60
|
+
t.get_an_enum("I like money").should == Tester::MyEnum::I_LIKE_MONEY
|
61
|
+
t.get_an_enum("You like money").should == Tester::MyEnum::YOU_LIKE_MONEY_TOO
|
62
|
+
end
|
63
|
+
end
|
data/test/file_writers_test.rb
CHANGED
@@ -23,10 +23,10 @@ context "Multiple file writer (default)" do
|
|
23
23
|
|
24
24
|
%w(
|
25
25
|
extconf.rb
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
26
|
+
_Mod.rb.cpp
|
27
|
+
_Mod.rb.hpp
|
28
|
+
_classes_Adder.rb.cpp
|
29
|
+
_classes_Adder.rb.hpp
|
30
30
|
adder.rb.cpp
|
31
31
|
).each do |wants|
|
32
32
|
assert_not_nil files.find {|got| File.basename(got) == wants }, "Didn't find #{wants}"
|
@@ -35,6 +35,37 @@ context "Multiple file writer (default)" do
|
|
35
35
|
|
36
36
|
end
|
37
37
|
|
38
|
+
context "Multiple file writer with to_from_ruby" do
|
39
|
+
|
40
|
+
setup do
|
41
|
+
@working_dir = File.expand_path(File.dirname(__FILE__) + "/generated")
|
42
|
+
|
43
|
+
e = Extension.new "to_from_ruby"
|
44
|
+
e.working_dir = @working_dir
|
45
|
+
e.sources full_dir("headers/to_from_ruby.h"),
|
46
|
+
:include_paths => full_dir("headers"),
|
47
|
+
:include_source_files => full_dir("headers/to_from_ruby_source.cpp")
|
48
|
+
|
49
|
+
e.namespace "to_from_ruby"
|
50
|
+
|
51
|
+
e.build
|
52
|
+
e.write
|
53
|
+
end
|
54
|
+
|
55
|
+
specify "should have proper written out files" do
|
56
|
+
files = Dir["#{@working_dir}/*"]
|
57
|
+
|
58
|
+
%w(
|
59
|
+
extconf.rb
|
60
|
+
_to_from_ruby.rb.hpp
|
61
|
+
_to_from_ruby.rb.cpp
|
62
|
+
).each do |wants|
|
63
|
+
assert_not_nil files.find {|got| File.basename(got) == wants }, "Didn't find #{wants}"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
38
69
|
context "Single file writer" do
|
39
70
|
|
40
71
|
setup do
|
@@ -66,3 +97,24 @@ context "Single file writer" do
|
|
66
97
|
end
|
67
98
|
|
68
99
|
end
|
100
|
+
|
101
|
+
context "Single file writer with to_from_ruby" do
|
102
|
+
|
103
|
+
setup do
|
104
|
+
Extension.new "to_from_ruby" do |e|
|
105
|
+
e.sources full_dir("headers/to_from_ruby.h"),
|
106
|
+
:include_paths => full_dir("headers"),
|
107
|
+
:include_source_files => full_dir("headers/to_from_ruby_source.cpp")
|
108
|
+
e.namespace "to_from_ruby"
|
109
|
+
|
110
|
+
e.writer_mode :single
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
specify "should have compiled properly" do
|
116
|
+
should.not.raise LoadError do
|
117
|
+
require 'to_from_ruby'
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
data/test/generated/extconf.rb
CHANGED
@@ -1,5 +1,25 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
require 'rubygems'
|
2
|
+
require 'mkmf-rice'
|
3
|
+
|
4
|
+
# Add the arguments to the linker flags.
|
5
|
+
def append_ld_flags(flags)
|
6
|
+
flags = [flags] unless flags.is_a?(Array)
|
7
|
+
with_ldflags("#{$LDFLAGS} #{flags.join(' ')}") { true }
|
8
|
+
end
|
9
|
+
|
10
|
+
$CPPFLAGS += " -I'/home/roelofs/projects/rbplusplus/test/generated' -I/home/roelofs/projects/rbplusplus/test/headers "
|
11
|
+
$LDFLAGS += " "
|
12
|
+
|
13
|
+
if RUBY_PLATFORM =~ /darwin/
|
14
|
+
# In order to link the shared library into our bundle with GCC 4.x on OSX, we have to work around a bug:
|
15
|
+
# GCC redefines symbols - which the -fno-common prohibits. In order to keep the -fno-common, we
|
16
|
+
# remove the flat_namespace (we now have two namespaces, which fixes the GCC clash). Also, we now lookup
|
17
|
+
# symbols in both the namespaces (dynamic_lookup).
|
18
|
+
|
19
|
+
$LDSHARED_CXX.gsub!('suppress', 'dynamic_lookup')
|
20
|
+
$LDSHARED_CXX.gsub!('-flat_namespace', '')
|
21
|
+
|
22
|
+
append_ld_flags '-all_load'
|
23
|
+
end
|
24
|
+
|
25
|
+
create_makefile("to_from_ruby")
|
@@ -0,0 +1,41 @@
|
|
1
|
+
namespace encapsulation {
|
2
|
+
class Base {
|
3
|
+
protected:
|
4
|
+
virtual int protectedMethod() {
|
5
|
+
return -1;
|
6
|
+
}
|
7
|
+
public:
|
8
|
+
virtual int fundamentalTypeVirtualMethod() = 0;
|
9
|
+
virtual ~Base() {}
|
10
|
+
virtual Base *userDefinedTypeVirtualMethod() = 0;
|
11
|
+
};
|
12
|
+
|
13
|
+
class Extended : public Base {
|
14
|
+
private:
|
15
|
+
void privateMethod() {
|
16
|
+
}
|
17
|
+
protected:
|
18
|
+
int protectedMethod() {
|
19
|
+
return 1;
|
20
|
+
}
|
21
|
+
public:
|
22
|
+
Extended() {}
|
23
|
+
int publicMethod() {
|
24
|
+
return this->protectedMethod();
|
25
|
+
}
|
26
|
+
int fundamentalTypeVirtualMethod() {
|
27
|
+
return 1;
|
28
|
+
}
|
29
|
+
Base *userDefinedTypeVirtualMethod() {
|
30
|
+
return new Extended();
|
31
|
+
}
|
32
|
+
};
|
33
|
+
|
34
|
+
class ExtendedFactory {
|
35
|
+
public:
|
36
|
+
ExtendedFactory() {}
|
37
|
+
Base *newInstance() {
|
38
|
+
return new Extended();
|
39
|
+
}
|
40
|
+
};
|
41
|
+
}
|
@@ -0,0 +1,25 @@
|
|
1
|
+
#ifndef __COMPLEX_H__
|
2
|
+
#define __COMPLEX_H__
|
3
|
+
|
4
|
+
namespace complex {
|
5
|
+
class SmallInteger {
|
6
|
+
private:
|
7
|
+
int i;
|
8
|
+
public:
|
9
|
+
SmallInteger(int i) {
|
10
|
+
this->i = i;
|
11
|
+
}
|
12
|
+
int getI() {
|
13
|
+
return this->i;
|
14
|
+
}
|
15
|
+
};
|
16
|
+
|
17
|
+
class Multiply {
|
18
|
+
public:
|
19
|
+
static int multiply(SmallInteger *i, SmallInteger *i2) {
|
20
|
+
return i->getI() * i2->getI();
|
21
|
+
}
|
22
|
+
};
|
23
|
+
}
|
24
|
+
|
25
|
+
#endif
|
@@ -0,0 +1,47 @@
|
|
1
|
+
#ifndef __CONSTRUCTORS_H__
|
2
|
+
#define __CONSTRUCTORS_H__
|
3
|
+
|
4
|
+
#include <string>
|
5
|
+
|
6
|
+
using namespace std;
|
7
|
+
|
8
|
+
namespace constructors {
|
9
|
+
class StringHolder {
|
10
|
+
private:
|
11
|
+
std::string name;
|
12
|
+
public:
|
13
|
+
StringHolder() { }
|
14
|
+
StringHolder(std::string name) {
|
15
|
+
setName(name);
|
16
|
+
}
|
17
|
+
inline std::string getName() {
|
18
|
+
return name;
|
19
|
+
}
|
20
|
+
inline void setName(std::string name) {
|
21
|
+
this->name = name;
|
22
|
+
}
|
23
|
+
};
|
24
|
+
|
25
|
+
class DoubleStringHolder {
|
26
|
+
private:
|
27
|
+
StringHolder *one, *two;
|
28
|
+
public:
|
29
|
+
DoubleStringHolder(StringHolder *one, StringHolder *two) {
|
30
|
+
this->one = one;
|
31
|
+
this->two = two;
|
32
|
+
}
|
33
|
+
inline StringHolder *getOne() {
|
34
|
+
return this->one;
|
35
|
+
}
|
36
|
+
inline StringHolder *getTwo() {
|
37
|
+
return this->two;
|
38
|
+
}
|
39
|
+
};
|
40
|
+
|
41
|
+
class PrivateConstructor {
|
42
|
+
private:
|
43
|
+
PrivateConstructor() {}
|
44
|
+
};
|
45
|
+
}
|
46
|
+
|
47
|
+
#endif
|