rbplusplus 0.9.1 → 1.0

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.
Files changed (53) hide show
  1. data/Rakefile +4 -9
  2. data/lib/rbplusplus/builders/allocation_strategy.rb +0 -7
  3. data/lib/rbplusplus/builders/base.rb +11 -5
  4. data/lib/rbplusplus/builders/class.rb +5 -14
  5. data/lib/rbplusplus/builders/const.rb +1 -1
  6. data/lib/rbplusplus/builders/constructor.rb +1 -1
  7. data/lib/rbplusplus/builders/director.rb +13 -13
  8. data/lib/rbplusplus/builders/enumeration.rb +2 -2
  9. data/lib/rbplusplus/builders/helpers/class.rb +17 -2
  10. data/lib/rbplusplus/builders/helpers/implicit_caster.rb +0 -0
  11. data/lib/rbplusplus/builders/implicit_caster.rb +24 -0
  12. data/lib/rbplusplus/builders/instance_variable.rb +4 -4
  13. data/lib/rbplusplus/builders/method_base.rb +8 -7
  14. data/lib/rbplusplus/builders/module.rb +1 -1
  15. data/lib/rbplusplus/logger.rb +13 -4
  16. data/lib/rbplusplus/transformers/class.rb +43 -34
  17. data/lib/rbplusplus/transformers/constructor.rb +30 -0
  18. data/lib/rbplusplus/transformers/function.rb +3 -3
  19. data/lib/rbplusplus/transformers/method.rb +2 -2
  20. data/lib/rbplusplus/transformers/node.rb +10 -17
  21. data/lib/rbplusplus/writers/multiple_files_writer.rb +8 -6
  22. data/lib/rbplusplus.rb +2 -1
  23. data/test/allocation_strategies_test.rb +21 -14
  24. data/test/class_methods_encapsulate_test.rb +25 -25
  25. data/test/class_methods_test.rb +7 -12
  26. data/test/classes_test.rb +36 -40
  27. data/test/compiling_test.rb +23 -19
  28. data/test/constructors_test.rb +5 -5
  29. data/test/custom_code_test.rb +25 -32
  30. data/test/default_arguments_test.rb +38 -42
  31. data/test/director_test.rb +51 -53
  32. data/test/enumerations_test.rb +37 -41
  33. data/test/extension_test.rb +10 -10
  34. data/test/file_writers_test.rb +17 -21
  35. data/test/function_pointer_test.rb +9 -13
  36. data/test/function_pointers_classes_test.rb +7 -11
  37. data/test/functions_test.rb +4 -10
  38. data/test/generated/extconf.rb +2 -2
  39. data/test/headers/alloc_strats.h +3 -1
  40. data/test/headers/implicit_cast.h +107 -0
  41. data/test/headers/to_from_ruby.h +13 -6
  42. data/test/headers/to_from_ruby_source.cpp +2 -2
  43. data/test/implicit_cast_test.rb +67 -0
  44. data/test/modules_test.rb +39 -40
  45. data/test/nested_test.rb +14 -16
  46. data/test/overloading_test.rb +17 -20
  47. data/test/struct_test.rb +4 -6
  48. data/test/subclass_test.rb +10 -12
  49. data/test/test_helper.rb +21 -12
  50. data/test/to_from_ruby_test.rb +7 -1
  51. data/test/wrap_as_test.rb +32 -29
  52. metadata +170 -108
  53. data/lib/rbplusplus/transformers/node_cache.rb +0 -15
@@ -1,6 +1,6 @@
1
1
  require 'test_helper'
2
2
 
3
- context "Extension with globally available functions" do
3
+ describe "Extension with globally available functions" do
4
4
 
5
5
  specify "should make functions available" do
6
6
  Extension.new "functions" do |e|
@@ -10,17 +10,11 @@ context "Extension with globally available functions" do
10
10
 
11
11
  require 'functions'
12
12
 
13
- should.not.raise NameError do
14
- test1
15
- end
13
+ lambda { test1 }.should_not raise_error(NameError)
16
14
 
17
- should.not.raise NameError do
18
- assert_in_delta 1.0, test2(2.0), 0.001
19
- end
15
+ test2(2.0).should be_close(1.0, 0.001)
20
16
 
21
- should.not.raise NameError do
22
- test3(2, 4.2).should == 2
23
- end
17
+ test3(2, 4.2).should == 2
24
18
  end
25
19
 
26
20
  end
@@ -7,7 +7,7 @@ def append_ld_flags(flags)
7
7
  with_ldflags("#{$LDFLAGS} #{flags.join(' ')}") { true }
8
8
  end
9
9
 
10
- $CPPFLAGS += " -I'/home/roelofs/projects/rbplusplus/test/generated' "
10
+ $CPPFLAGS += " -I'/Users/roelofs/Development/rbplusplus/test/generated' "
11
11
  $LDFLAGS += " "
12
12
 
13
13
  if RUBY_PLATFORM =~ /darwin/
@@ -22,4 +22,4 @@ if RUBY_PLATFORM =~ /darwin/
22
22
  append_ld_flags '-all_load'
23
23
  end
24
24
 
25
- create_makefile("defargs")
25
+ create_makefile("ui")
@@ -18,7 +18,9 @@ namespace alloc_strats {
18
18
  public:
19
19
  NoConstructor* getConstructor() { return 0; }
20
20
 
21
- Neither* getInstance() { return 0; }
21
+ static Neither* getInstance() { static Neither neither; return &neither; }
22
+
23
+ int process(int a, int b) { return a * b; }
22
24
  };
23
25
  }
24
26
 
@@ -0,0 +1,107 @@
1
+ #ifndef __IMPLICIT_CAST_H__
2
+ #define __IMPLICIT_CAST_H__
3
+
4
+ namespace implicit_cast {
5
+
6
+ const int degree2Radians = (3.14 / 180.0);
7
+ const int radian2Degrees = (180.0 / 3.14);
8
+
9
+ class Radian;
10
+
11
+ class Degree
12
+ {
13
+ public:
14
+ explicit Degree(float d) : val_(d) {}
15
+ Degree(const Radian& r);
16
+
17
+ float valueDegrees() const { return val_; }
18
+ float valueRadians() const { return val_ * degree2Radians; }
19
+
20
+ private:
21
+ float val_;
22
+ };
23
+
24
+ class Radian
25
+ {
26
+ public:
27
+ explicit Radian(float r) : val_(r) {}
28
+ Radian(const Degree& d) : val_(d.valueRadians()) {}
29
+
30
+ float valueRadians() const { return val_; }
31
+ float valueDegrees() const { return val_ * radian2Degrees; }
32
+
33
+ private:
34
+ float val_;
35
+ };
36
+
37
+ // Due to circular dependencies, need to define some
38
+ // methods down here
39
+ Degree::Degree(const Radian& r)
40
+ {
41
+ val_ = r.valueDegrees();
42
+ }
43
+
44
+ /**
45
+ * And now some methods that work w/ the above two classes
46
+ */
47
+ bool isAcute(Degree degree) {
48
+ return degree.valueDegrees() < 90;
49
+ }
50
+
51
+ bool isObtuse(Radian radian) {
52
+ return radian.valueDegrees() > 90 && radian.valueDegrees() <= 180;
53
+ }
54
+
55
+ bool isRight(Degree* degree) {
56
+ return degree->valueDegrees() == 90;
57
+ }
58
+
59
+ /**
60
+ * Classes to show how to turn off the implicit casting
61
+ */
62
+ class Explicit
63
+ {
64
+ public:
65
+ Explicit(float v) {
66
+ value = v;
67
+ }
68
+
69
+ Explicit(const Degree &d) {
70
+ value = d.valueDegrees();
71
+ }
72
+
73
+ Explicit(const Radian &r) {
74
+ value = r.valueDegrees();
75
+ }
76
+
77
+ float value;
78
+ };
79
+
80
+ float explicitValue(Explicit e) {
81
+ return e.value;
82
+ }
83
+
84
+ class NotImplicit
85
+ {
86
+ public:
87
+ NotImplicit(float v, int a) {
88
+ value = v * a;
89
+ }
90
+
91
+ NotImplicit(const Degree &d) {
92
+ value = d.valueDegrees();
93
+ }
94
+
95
+ NotImplicit(const Radian &r) {
96
+ value = r.valueDegrees();
97
+ }
98
+
99
+ float value;
100
+ };
101
+
102
+ float notImplicitValue(NotImplicit i) {
103
+ return i.value;
104
+ }
105
+ }
106
+
107
+ #endif
@@ -26,7 +26,11 @@ namespace to_from_ruby {
26
26
  // Should also work with class methods
27
27
  class WrappedClass {
28
28
  public:
29
- WrappedClass() {}
29
+ WrappedClass() { myType = new MyType(); }
30
+
31
+ ~WrappedClass() {
32
+ if(myType) { delete myType; }
33
+ }
30
34
 
31
35
  const MyType& getMyType(int value) {
32
36
  MyType *type = new MyType();
@@ -34,20 +38,23 @@ namespace to_from_ruby {
34
38
  return *type;
35
39
  }
36
40
 
37
- const WrappedClass &overload() {
38
- return *this;
41
+ const MyType &overload() {
42
+ return *myType;
39
43
  }
40
44
 
41
- const WrappedClass &overload(int arg) {
42
- return *this;
45
+ const MyType &overload(int arg) {
46
+ return *myType;
43
47
  }
48
+
49
+ private:
50
+ const MyType* myType;
44
51
  };
45
52
 
46
53
  /**
47
54
  * Some types, Rice already wraps for us. Make sure this doesn't cause
48
55
  * a compiler error
49
56
  */
50
- void usingConstString(const std::string& in);
57
+ int usingConstString(const std::string& in);
51
58
 
52
59
  /* template tests */
53
60
 
@@ -16,7 +16,7 @@ namespace to_from_ruby {
16
16
  return *type;
17
17
  };
18
18
 
19
- void usingConstString(const std::string& in) {
20
-
19
+ int usingConstString(const std::string& in) {
20
+ return in.size();
21
21
  }
22
22
  }
@@ -0,0 +1,67 @@
1
+ require 'test_helper'
2
+
3
+ describe "Specify types to allow implicit casting" do
4
+
5
+ before(:all) do
6
+ Extension.new "implicit_cast" do |e|
7
+ e.sources full_dir("headers/implicit_cast.h")
8
+ e.writer_mode :single
9
+
10
+ node = e.namespace "implicit_cast"
11
+
12
+ # Can flag individual constructors
13
+ node.classes("Explicit").constructors.
14
+ find(:arguments => ["const Radian&"]).implicit_casting(false)
15
+
16
+ # Or flag the class as a whole
17
+ node.classes("NotImplicit").implicit_casting(false)
18
+ end
19
+
20
+ require 'implicit_cast'
21
+ end
22
+
23
+ specify "proper constructor is exposed" do
24
+ Degree.new(14).value_degrees.should == 14
25
+ Radian.new(1).value_radians.should == 1
26
+ end
27
+
28
+ specify "can use Degree in place of Radian" do
29
+ is_obtuse(Degree.new(75)).should be_false
30
+ end
31
+
32
+ specify "can use Radian in place of Degree" do
33
+ is_acute(Radian.new(2.0)).should be_false
34
+ end
35
+
36
+ specify "pointers also work fine" do
37
+ is_right(Degree.new(90)).should be_true
38
+ is_right(Radian.new(2.0)).should be_false
39
+ end
40
+
41
+ specify "can turn off implicit cast wrapping for a given constructor" do
42
+ lambda do
43
+ explicit_value(Radian.new(60.0))
44
+ end.should raise_error
45
+
46
+ lambda do
47
+ e = Explicit.new(14.0)
48
+ explicit_value(e).should be_close(14.0, 0.001)
49
+ end.should_not raise_error
50
+ end
51
+
52
+ specify "can turn off implicit casting for an entire class" do
53
+ n = NotImplicit.new(10.0, 3)
54
+
55
+ not_implicit_value(n).should be_close(30.0, 0.001)
56
+
57
+ lambda do
58
+ not_implicit_value(Degree.new(15.0))
59
+ end.should raise_error
60
+
61
+ lambda do
62
+ not_implicit_value(Radian.new(1.0))
63
+ end.should raise_error
64
+ end
65
+
66
+ end
67
+
data/test/modules_test.rb CHANGED
@@ -2,70 +2,69 @@ require 'test_helper'
2
2
 
3
3
  context "Extension with modules" do
4
4
 
5
- def setup
6
- if !defined?(@@modules_built)
7
- super
8
- @@modules_built = true
9
- Extension.new "modules" do |e|
10
- e.sources [
11
- full_dir("headers/Adder.h"),
12
- full_dir("headers/functions.h"),
13
- full_dir("headers/Subtracter.hpp")
14
- ],
15
- :include_source_files => [
16
- full_dir("headers/Adder.h"),
17
- full_dir("headers/Adder.cpp")
18
- ]
19
-
20
- e.writer_mode :single
21
-
22
- e.module "Empty" do |m|
23
- end
5
+ before(:all) do
6
+ Extension.new "modules" do |e|
7
+ e.sources [
8
+ full_dir("headers/Adder.h"),
9
+ full_dir("headers/functions.h"),
10
+ full_dir("headers/Subtracter.hpp")
11
+ ],
12
+ :include_source_files => [
13
+ full_dir("headers/Adder.h"),
14
+ full_dir("headers/Adder.cpp")
15
+ ]
24
16
 
25
- # Can use without a block
26
- wrapper = e.module "Wrapper"
27
- node = wrapper.namespace "classes"
28
- node.classes("Adder").disable_typedef_lookup
17
+ e.writer_mode :single
29
18
 
30
- e.module "Functions" do |m|
31
- m.namespace "functions"
32
- end
19
+ e.module "Empty" do |m|
20
+ end
21
+
22
+ # Can use without a block
23
+ wrapper = e.module "Wrapper"
24
+ node = wrapper.namespace "classes"
25
+ node.classes("Adder").disable_typedef_lookup
26
+
27
+ e.module "Functions" do |m|
28
+ m.namespace "functions"
29
+ end
33
30
 
34
- e.module "Nested" do |m|
35
- m.module "Nested" do |n|
36
- n.module "Inner" do |inner|
37
- inner.namespace "subtracter"
38
- end
31
+ e.module "Nested" do |m|
32
+ m.module "Nested" do |n|
33
+ n.module "Inner" do |inner|
34
+ inner.namespace "subtracter"
39
35
  end
40
36
  end
41
-
42
37
  end
43
38
 
44
- require 'modules'
45
39
  end
40
+
41
+ require 'modules'
46
42
  end
47
43
 
48
44
  specify "should be able to generate a module definition" do
49
- assert defined?(Empty)
45
+ lambda { Empty }.should_not raise_error(NameError)
46
+
50
47
  Empty.class.should == Module
51
48
  end
52
49
 
53
50
  specify "should wrap up C++ classes under the namespace as requested" do
54
- assert !defined?(Adder)
55
- assert defined?(Wrapper::Adder)
51
+ lambda { Adder }.should raise_error(NameError)
52
+ lambda { Wrapper::Adder }.should_not raise_error(NameError)
53
+
56
54
  a = Wrapper::Adder.new
57
55
  a.get_class_name.should == "Adder"
58
56
  end
59
57
 
60
58
  specify "should wrap up C++ functions in the module" do
61
- assert defined?(Functions)
62
- Functions::test2(2).should.be.close 1.0, 0.001
59
+ lambda { Functions }.should_not raise_error(NameError)
60
+ Functions::test2(2).should be_close(1.0, 0.001)
63
61
  Functions::test3(4, 6).should == 4
64
62
  end
65
63
 
66
64
  specify "should be able to nest modules and related definitions" do
67
- assert !defined?(Subtracter)
68
- assert defined?(Nested::Nested::Inner::Subtracter)
65
+ lambda { Subtracter }.should raise_error(NameError)
66
+ lambda { Nested::Nested::Inner::Subtracter }.should_not raise_error(NameError)
67
+
69
68
  s = Nested::Nested::Inner::Subtracter.new
70
69
  s.get_class_name.should == "Subtracter"
71
70
  end
data/test/nested_test.rb CHANGED
@@ -1,26 +1,24 @@
1
1
  require 'test_helper'
2
2
 
3
3
  context "Wrapping Classes within classes" do
4
- def setup
5
- if !defined?(@@nested_built)
6
- super
7
- @@nested_built = true
8
- Extension.new "nested" do |e|
9
- e.sources full_dir("headers/nested_classes.h")
10
- node = e.namespace "classes"
11
- end
12
-
13
- require 'nested'
4
+ before(:all) do
5
+ Extension.new "nested" do |e|
6
+ e.sources full_dir("headers/nested_classes.h")
7
+ node = e.namespace "classes"
14
8
  end
9
+
10
+ require 'nested'
15
11
  end
16
12
 
17
13
  specify "should properly make nested classes available" do
18
- assert defined?(TestClass)
19
- assert defined?(TestClass::InnerClass)
20
- assert defined?(TestClass::InnerClass::Inner2)
14
+ lambda do
15
+ Kernel.const_get(TestClass)
16
+ Kernel.const_get(TestClass::InnerClass)
17
+ Kernel.const_get(TestClass::InnerClass::Inner2)
18
+ end.should_not raise_error(NameError)
21
19
 
22
- TestClass.new.should.not.be.nil
23
- TestClass::InnerClass.new.should.not.be.nil
24
- TestClass::InnerClass::Inner2.new.should.not.be.nil
20
+ TestClass.new.should_not be_nil
21
+ TestClass::InnerClass.new.should_not be_nil
22
+ TestClass::InnerClass::Inner2.new.should_not be_nil
25
23
  end
26
24
  end
@@ -1,6 +1,6 @@
1
1
  require 'test_helper'
2
2
 
3
- context "Extension with overloaded methods" do
3
+ describe "Extension with overloaded methods" do
4
4
 
5
5
  specify "should have all functions available" do
6
6
  Extension.new "overload" do |e|
@@ -12,35 +12,32 @@ context "Extension with overloaded methods" do
12
12
  mathy.use_constructor(
13
13
  mathy.constructors.find(:arguments => [:int])
14
14
  )
15
+
16
+ mathy.methods("constMethod").find(:arguments => ["std::string"]).wrap_as("const_method_string")
15
17
  end
16
18
 
17
19
  require 'overload'
18
20
 
19
- math = nil
20
- should.not.raise NameError do
21
- #Constructor overloading is broken in rice
22
- #math = Mathy.new
23
- math = Mathy.new(1)
24
- end
21
+ #Constructor overloading is broken in rice
22
+ #math = Mathy.new
23
+ math = Mathy.new(1)
25
24
 
26
- should.not.raise NameError do
27
- math.times.should.equal 1
28
- math.times_1(3).should.equal 3
29
- math.times_2(3,2).should.equal 6
30
- math.times_3(3,2,3).should.equal 18
31
- end
25
+ math.times.should == 1
26
+ math.times_1(3).should == 3
27
+ math.times_2(3,2).should == 6
28
+ math.times_3(3,2,3).should == 18
32
29
 
33
- should.not.raise NameError do
30
+ lambda do
34
31
  math.nothing_0
35
32
  math.nothing_1(1)
36
- end
33
+ end.should_not raise_error(NameError)
37
34
 
38
35
  # Should properly handle const overloads as well
39
- should.not.raise NameError do
40
- math.const_method_0(1).should.equal 1
41
- math.const_method_1(1).should.equal 2
42
- math.const_method_2("love").should.equal 4
43
- end
36
+ lambda do
37
+ math.const_method_0(1)
38
+ math.const_method_1(1)
39
+ math.const_method_string("love")
40
+ end.should_not raise_error(NameError)
44
41
 
45
42
  end
46
43
 
data/test/struct_test.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  require 'test_helper'
2
2
 
3
- context "Nested Struct" do
3
+ describe "Nested Struct" do
4
4
 
5
5
  specify "should be accessible" do
6
6
  Extension.new "nested" do |e|
@@ -10,13 +10,11 @@ context "Nested Struct" do
10
10
 
11
11
  require 'nested'
12
12
 
13
- should.not.raise NameError do
14
- Klass::NestedStruct.new.one.should == 1
15
- end
13
+ Klass::NestedStruct.new.one.should == 1
16
14
 
17
- should.raise NameError do
15
+ lambda do
18
16
  Klass::PrivateNestedStruct.new
19
- end
17
+ end.should raise_error(NameError)
20
18
  end
21
19
 
22
20
  end
@@ -12,30 +12,28 @@ context "Extension with class hierachies" do
12
12
  # Rice doesn't support multiple-inheritance (neither does Ruby), so for now
13
13
  # until we can fake it, force people to specify
14
14
  node.classes("Multiple").use_superclass( node.classes("Base2") )
15
+
16
+ node.classes.implicit_casting(false)
15
17
  end
16
18
 
17
19
  require 'subclass'
18
20
 
19
21
  # Ignored superclasses should not cause problems with wrapped subclasses
20
- should.not.raise NameError do
21
- Base.new.one.should == Sub.new.one
22
- Base.new.zero.should == Sub.new.zero
23
- end
22
+ Base.new.one.should == Sub.new.one
23
+ Base.new.zero.should == Sub.new.zero
24
24
 
25
25
  # Template superclasses shouldn't cause problems
26
- should.not.raise NameError do
27
- TemplateSub.new.zero.should == TemplateSub.new.custom
28
- end
26
+ TemplateSub.new.zero.should == TemplateSub.new.custom
29
27
 
30
- should.not.raise NameError do
28
+ lambda do
31
29
  TemplatePtr.new.custom
32
- end
30
+ end.should_not raise_error(NameError)
33
31
 
34
- should.not.raise NameError do
32
+ lambda do
35
33
  Multiple.new
36
- end
34
+ end.should_not raise_error(NameError)
37
35
 
38
- Multiple.superclass.should.equal Base2
36
+ Multiple.superclass.should == Base2
39
37
  end
40
38
 
41
39
  end
data/test/test_helper.rb CHANGED
@@ -2,28 +2,37 @@ $:.unshift File.expand_path(File.dirname(__FILE__) + "/../lib")
2
2
  $:.unshift File.expand_path(File.dirname(__FILE__) + "/generated")
3
3
 
4
4
  require 'rubygems'
5
- require 'test/spec'
5
+ require 'rspec'
6
6
  require 'rbplusplus'
7
- require 'mocha_standalone'
8
7
 
9
8
  include RbPlusPlus
10
9
 
11
- class Test::Unit::TestCase
12
-
10
+ module FileDirectoryHelpers
13
11
  def full_dir(path)
14
12
  File.expand_path(File.join(File.dirname(__FILE__), path))
15
13
  end
14
+ end
16
15
 
17
- def setup
16
+ module TestHelpers
17
+ def clear_info
18
18
  `rm -rf #{full_dir('generated')}/*`
19
- Logger.stubs(:info)
20
- Logger.stubs(:warn)
21
- Logger.stubs(:error)
22
- Logger.stubs(:debug)
23
19
  end
24
20
 
25
- def teardown
26
- RbGCCXML::XMLParsing.clear_cache
27
- NodeCache.clear
21
+ def silence_logging
22
+ RbPlusPlus::Logger.silent!
23
+ end
24
+
25
+ def test_setup
26
+ clear_info
27
+ silence_logging
28
+ end
29
+ end
30
+
31
+ RSpec.configure do |config|
32
+ config.include(FileDirectoryHelpers)
33
+ config.include(TestHelpers)
34
+
35
+ config.before(:all) do
36
+ test_setup
28
37
  end
29
38
  end
@@ -17,6 +17,12 @@ context "Properly build known required to_ruby and from_ruby methods" do
17
17
 
18
18
  c = WrappedClass.new
19
19
  c.get_my_type(17).value.should == 17
20
- c.overload_0.class.should == c.overload_1(0).class
20
+
21
+ using_const_string("super_long").should == 10
22
+
23
+ # Running this gets a glibc double free error. Not sure if this is properly
24
+ # fixable outside of implementing call and return policies in Rice.
25
+ # c.overload_0.class.should == MyType
26
+ # c.overload_0.class.should == c.overload_1(0).class
21
27
  end
22
28
  end