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
@@ -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
|