rice 1.3.2 → 1.4.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.
data/Doxyfile CHANGED
@@ -23,7 +23,7 @@ PROJECT_NAME = Rice
23
23
  # This could be handy for archiving the generated documentation or
24
24
  # if some version control system is used.
25
25
 
26
- PROJECT_NUMBER = 1.3.2
26
+ PROJECT_NUMBER = 1.4.0
27
27
 
28
28
  # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
29
29
  # base path where the generated documentation will be put.
data/README CHANGED
@@ -695,6 +695,12 @@ can be used as expected:
695
695
  t.hello("goodnight", "moon")
696
696
  \endcode
697
697
 
698
+ This will also work with Constructors:
699
+
700
+ \code
701
+ .define_constructor(Constructor<SomeClass, int, int>(),
702
+ ( Arg("arg1") = 1, Arg("otherArg") = 12 );
703
+ \endcode
698
704
 
699
705
  \section director Director
700
706
 
@@ -822,6 +828,43 @@ Rice::Data_Type::define_director, then define methods pointing to the proxy obje
822
828
  You must use the Rice::Director proxy class in the Constructor line, this allows proper
823
829
  object construction / destruction of the types in question.
824
830
 
831
+ \section implicit_cast Implicit Casting
832
+
833
+ There are times when a library exposes classes that while unrelated are
834
+ built to be interchangeable across the library. One example of this,
835
+ taken from Ogre, are the Degree and Radian classes. When a given method
836
+ takes a Radian, you're free to pass in a Degree, and vice versa.
837
+
838
+ Rice cannot automatically figure out if this kind of functionality is
839
+ possible in a given library but it does have a simple API for defining
840
+ these relationships: Rice::define_implicit_cast<From, To>().
841
+
842
+ \code
843
+ class Degree { ... };
844
+ class Radian { ... };
845
+
846
+ extern "C"
847
+ void Init_implicit() {
848
+ define_class<Degree>()
849
+ ...;
850
+ define_class<Radian>()
851
+ ...;
852
+
853
+ define_implicit_cast<Degree, Radian>();
854
+ define_implicit_cast<Radian, Degree>();
855
+ }
856
+ \endcode
857
+
858
+ This support is still being fleshed out and has a few requirements for
859
+ proper use:
860
+
861
+ \li The two types must be bound in Rice before defining the cast.
862
+ \li The classes must have constructors that take the other type.
863
+ \li This feature cannot be used with fundamental types yet.
864
+
865
+ To see a full example of this feature, please check out
866
+ test/test_Data_Type.cpp.
867
+
825
868
  \section motivation Motivation
826
869
 
827
870
  There are a number of common problems when writing C or C++ extensions
data/Rakefile CHANGED
@@ -1,7 +1,7 @@
1
+ $: << File.expand_path(File.dirname(__FILE__))
1
2
  require 'rake/gempackagetask'
2
3
  require 'rake/contrib/sshpublisher'
3
4
  require 'yaml'
4
- require 'rubyforge'
5
5
  require 'ruby/lib/version'
6
6
 
7
7
  PROJECT_NAME = "rice"
data/extconf.rb CHANGED
@@ -26,9 +26,11 @@ with_ruby = File.join(Config::CONFIG["bindir"], Config::CONFIG["RUBY_INSTALL_NAM
26
26
  other_opts = ""
27
27
  env = ""
28
28
 
29
+ arch = Config::CONFIG["arch"].split("-")[0]
30
+
29
31
  if RUBY_PLATFORM =~ /darwin10/
30
32
  other_opts = "--disable-dependency-tracking"
31
- env = "ARCHFLAGS='-arch x86_64'"
33
+ env = "ARCHFLAGS='-arch #{arch}'"
32
34
  elsif RUBY_PLATFORM =~ /darwin9/
33
35
  env = "ARCHFLAGS='-arch #{`uname -p`.chomp}'"
34
36
  end
@@ -121,7 +121,8 @@ template<typename T>
121
121
  template<typename Constructor_T>
122
122
  inline Rice::Data_Type<T> & Rice::Data_Type<T>::
123
123
  define_constructor(
124
- Constructor_T constructor)
124
+ Constructor_T /* constructor */,
125
+ Arguments* arguments)
125
126
  {
126
127
  check_is_bound();
127
128
 
@@ -129,11 +130,28 @@ define_constructor(
129
130
  rb_define_alloc_func(
130
131
  static_cast<VALUE>(*this),
131
132
  detail::default_allocation_func<T>);
132
- define_method("initialize", &Constructor_T::construct);
133
+ define_method(
134
+ "initialize",
135
+ &Constructor_T::construct,
136
+ arguments
137
+ );
133
138
 
134
139
  return *this;
135
140
  }
136
141
 
142
+ template<typename T>
143
+ template<typename Constructor_T>
144
+ inline Rice::Data_Type<T> & Rice::Data_Type<T>::
145
+ define_constructor(
146
+ Constructor_T constructor,
147
+ Arg const& arg)
148
+ {
149
+ Arguments* args = new Arguments();
150
+ args->add(arg);
151
+ return define_constructor(constructor, args);
152
+ }
153
+
154
+
137
155
  template<typename T>
138
156
  template<typename Director_T>
139
157
  inline Rice::Data_Type<T>& Rice::Data_Type<T>::
@@ -177,7 +195,7 @@ from_ruby(Object x)
177
195
 
178
196
  VALUE ancestors = rb_mod_ancestors(klass.value());
179
197
 
180
- int earliest = RARRAY_LEN(ancestors) + 1;
198
+ long earliest = RARRAY_LEN(ancestors) + 1;
181
199
 
182
200
  int index;
183
201
  VALUE indexFound;
@@ -312,4 +330,36 @@ define_class(
312
330
  return Data_Type<T>::template bind<Base_T>(c);
313
331
  }
314
332
 
333
+ template<typename From_T, typename To_T>
334
+ inline void
335
+ Rice::define_implicit_cast()
336
+ {
337
+ // As Rice currently expects only one entry into
338
+ // this list for a given klass VALUE, we need to get
339
+ // the current caster for From_T and insert in our
340
+ // new caster as the head of the caster list
341
+
342
+ Class from_class = Data_Type<From_T>::klass().value();
343
+ Class to_class = Data_Type<To_T>::klass().value();
344
+
345
+ detail::Abstract_Caster* from_caster =
346
+ Data_Type<From_T>::caster_.release();
347
+
348
+ detail::Abstract_Caster* new_caster =
349
+ new detail::Implicit_Caster<To_T, From_T>(from_caster, to_class);
350
+
351
+ // Insert our new caster into the list for the from class
352
+ Data_Type_Base::casters().erase(from_class);
353
+ Data_Type_Base::casters().insert(
354
+ std::make_pair(
355
+ from_class,
356
+ new_caster
357
+ )
358
+ );
359
+
360
+ // And make sure the from_class has direct access to the
361
+ // updated caster list
362
+ Data_Type<From_T>::caster_.reset(new_caster);
363
+ }
364
+
315
365
  #endif // Rice__Data_Type__ipp_
@@ -39,7 +39,6 @@ public:
39
39
  // Must be public to workaround gcc 3.3
40
40
  typedef std::map<VALUE, detail::Abstract_Caster *> Casters;
41
41
 
42
- protected:
43
42
  virtual detail::Abstract_Caster * caster() const = 0;
44
43
 
45
44
  static Casters & casters();
@@ -93,6 +92,15 @@ template<typename T, typename Base_T>
93
92
  Rice::Data_Type<T> define_class(
94
93
  char const * name);
95
94
 
95
+ //! Define an implicit conversion rule between two types.
96
+ /*! Given two types, which can be custom types already
97
+ * wrapped into Rice or fundamental C++ types, this
98
+ * tells Rice that the two types can be used interchangably.
99
+ * \param From_T The type to convert from
100
+ * \param To_T The type to convert to
101
+ */
102
+ template<typename From_T, typename To_T>
103
+ void define_implicit_cast();
96
104
 
97
105
  //! A mechanism for binding ruby types to C++ types.
98
106
  /*! This class binds run-time types (Ruby VALUEs) to compile-time types
@@ -151,7 +159,13 @@ public:
151
159
  */
152
160
  template<typename Constructor_T>
153
161
  Data_Type<T> & define_constructor(
154
- Constructor_T constructor);
162
+ Constructor_T constructor,
163
+ Arguments * arguments = 0);
164
+
165
+ template<typename Constructor_T>
166
+ Data_Type<T> & define_constructor(
167
+ Constructor_T constructor,
168
+ Arg const& arg);
155
169
 
156
170
  //! Register a Director class for this class.
157
171
  /*! For any class that uses Rice::Director to enable polymorphism
@@ -188,6 +202,10 @@ public:
188
202
  */
189
203
  static bool is_bound();
190
204
 
205
+ virtual detail::Abstract_Caster * caster() const;
206
+
207
+ static std::auto_ptr<detail::Abstract_Caster> caster_;
208
+
191
209
  protected:
192
210
  //! Bind a Data_Type to a VALUE.
193
211
  /*! Throws an exception if the Data_Type is already bound to a
@@ -221,12 +239,9 @@ private:
221
239
  template<typename T_>
222
240
  friend class Data_Type;
223
241
 
224
- virtual detail::Abstract_Caster * caster() const;
225
-
226
242
  static void check_is_bound();
227
243
 
228
244
  static VALUE klass_;
229
- static std::auto_ptr<detail::Abstract_Caster> caster_;
230
245
 
231
246
  typedef std::set<Data_Type<T> *> Instances;
232
247
 
@@ -2,19 +2,19 @@
2
2
  /* rice/config.hpp.in. Generated from configure.ac by autoheader. */
3
3
 
4
4
  /* Define to 1 if you have the <env.h> header file. */
5
- #define HAVE_ENV_H 1
5
+ /* #undef HAVE_ENV_H */
6
6
 
7
7
  /* Define to 1 if you have the <node.h> header file. */
8
- #define HAVE_NODE_H 1
8
+ /* #undef HAVE_NODE_H */
9
9
 
10
10
  /* Define to 1 if you have the <ruby.h> header file. */
11
11
  #define HAVE_RUBY_H 1
12
12
 
13
13
  /* Define to 1 if you have the <ruby/node.h> header file. */
14
- #define HAVE_RUBY_NODE_H 1
14
+ /* #undef HAVE_RUBY_NODE_H */
15
15
 
16
16
  /* Define to 1 if you have the <version.h> header file. */
17
- #define HAVE_VERSION_H 1
17
+ /* #undef HAVE_VERSION_H */
18
18
 
19
19
  /* Name of package */
20
20
  #define PACKAGE "rice"
@@ -35,7 +35,7 @@
35
35
  #define PACKAGE_VERSION "1.1"
36
36
 
37
37
  /* Define this macro to use ruby/node.h */
38
- #define REALLY_HAVE_RUBY_NODE_H
38
+ /* #undef REALLY_HAVE_RUBY_NODE_H */
39
39
 
40
40
  /* Version number of package */
41
41
  #define VERSION "1.1"
@@ -56,6 +56,46 @@ private:
56
56
  Module type_;
57
57
  };
58
58
 
59
+ template<typename To_T, typename From_T>
60
+ class Implicit_Caster
61
+ : public Abstract_Caster
62
+ {
63
+ public:
64
+ Implicit_Caster(Abstract_Caster * base_caster, Module type)
65
+ : base_caster_(base_caster)
66
+ , type_(type)
67
+ {
68
+ }
69
+
70
+ protected:
71
+ virtual void * cast_to_base(void * derived, Module type) const
72
+ {
73
+ if(type.value() == type_.value())
74
+ {
75
+ return new To_T( *static_cast<From_T*>(derived) );
76
+ }
77
+ else
78
+ {
79
+ if(base_caster_)
80
+ {
81
+ return base_caster_->cast_to_base(derived, type);
82
+ }
83
+ else
84
+ {
85
+ std::string s = "bad cast. No implicit caster found for ";
86
+ s += type_.name().str();
87
+ throw std::runtime_error(s);
88
+ }
89
+ }
90
+ }
91
+
92
+ private:
93
+ Abstract_Caster * base_caster_;
94
+ Module type_;
95
+ };
96
+
97
+
98
+
59
99
  } // detail
60
100
 
61
101
  } // Rice
@@ -1,6 +1,6 @@
1
1
  #ifndef Rice__detail__ruby_version_code__hpp
2
2
  #define Rice__detail__ruby_version_code__hpp
3
3
 
4
- #define RICE__RUBY_VERSION_CODE 187
4
+ #define RICE__RUBY_VERSION_CODE 192
5
5
 
6
6
  #endif // Rice__detail__ruby_version_code__hpp
@@ -7,8 +7,7 @@ convert(T const & x)
7
7
  {
8
8
  if(Data_Type<T>::is_bound())
9
9
  {
10
- Data_Object<T> obj(&const_cast<T&>(x));
11
- return obj;
10
+ return Rice::Data_Object<T >(new T(x), Rice::Data_Type<T >::klass());
12
11
  }
13
12
  else
14
13
  {
@@ -6,7 +6,7 @@
6
6
  * the default behavior (which is to not mark any additional objects).
7
7
  */
8
8
  template<typename T>
9
- void ruby_mark(T * obj)
9
+ void ruby_mark(T * /* obj */)
10
10
  {
11
11
  }
12
12
 
@@ -190,7 +190,7 @@ class RiceMakefileCreator
190
190
  end
191
191
 
192
192
  def puts(*strings)
193
- print(*strings.map { |s| "#{s}\n" })
193
+ print(*strings.flatten.map { |s| "#{s}\n" })
194
194
  end
195
195
 
196
196
  def close
@@ -1,3 +1,3 @@
1
1
  module Rice
2
- VERSION = "1.3.2"
2
+ VERSION = "1.4.0"
3
3
  end
@@ -1,3 +1,4 @@
1
+ $: << "."
1
2
  require 'sample_enum'
2
3
 
3
4
  Sample_Enum.each { |x| p x }
@@ -46,6 +46,7 @@ unittest_SOURCES = \
46
46
  test_Hash.cpp \
47
47
  test_Identifier.cpp \
48
48
  test_Jump_Tag.cpp \
49
+ test_Memory_Management.cpp \
49
50
  test_Module.cpp \
50
51
  test_Object.cpp \
51
52
  test_String.cpp \
@@ -60,6 +61,7 @@ vm_unittest_SOURCES = \
60
61
 
61
62
  AM_CPPFLAGS = \
62
63
  -I.. \
64
+ $(RUBY_CFLAGS)
63
65
  $(RUBY_CPPFLAGS)
64
66
 
65
67
  AM_CXXLAGS = \
@@ -54,10 +54,10 @@ am_unittest_OBJECTS = unittest.$(OBJEXT) \
54
54
  test_Director.$(OBJEXT) test_Enum.$(OBJEXT) \
55
55
  test_Exception.$(OBJEXT) test_Hash.$(OBJEXT) \
56
56
  test_Identifier.$(OBJEXT) test_Jump_Tag.$(OBJEXT) \
57
- test_Module.$(OBJEXT) test_Object.$(OBJEXT) \
58
- test_String.$(OBJEXT) test_Struct.$(OBJEXT) \
59
- test_Symbol.$(OBJEXT) test_To_From_Ruby.$(OBJEXT) \
60
- test_global_functions.$(OBJEXT)
57
+ test_Memory_Management.$(OBJEXT) test_Module.$(OBJEXT) \
58
+ test_Object.$(OBJEXT) test_String.$(OBJEXT) \
59
+ test_Struct.$(OBJEXT) test_Symbol.$(OBJEXT) \
60
+ test_To_From_Ruby.$(OBJEXT) test_global_functions.$(OBJEXT)
61
61
  unittest_OBJECTS = $(am_unittest_OBJECTS)
62
62
  unittest_LDADD = $(LDADD)
63
63
  am_vm_unittest_OBJECTS = unittest.$(OBJEXT) test_VM.$(OBJEXT)
@@ -237,6 +237,7 @@ unittest_SOURCES = \
237
237
  test_Hash.cpp \
238
238
  test_Identifier.cpp \
239
239
  test_Jump_Tag.cpp \
240
+ test_Memory_Management.cpp \
240
241
  test_Module.cpp \
241
242
  test_Object.cpp \
242
243
  test_String.cpp \
@@ -251,7 +252,7 @@ vm_unittest_SOURCES = \
251
252
 
252
253
  AM_CPPFLAGS = \
253
254
  -I.. \
254
- $(RUBY_CPPFLAGS)
255
+ $(RUBY_CFLAGS)
255
256
 
256
257
  AM_CXXLAGS = \
257
258
  $(RUBY_CXXFLAGS)
@@ -324,6 +325,7 @@ distclean-compile:
324
325
  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_Hash.Po@am__quote@
325
326
  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_Identifier.Po@am__quote@
326
327
  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_Jump_Tag.Po@am__quote@
328
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_Memory_Management.Po@am__quote@
327
329
  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_Module.Po@am__quote@
328
330
  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_Object.Po@am__quote@
329
331
  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_String.Po@am__quote@
@@ -720,6 +722,7 @@ check: run_multiple_extensions_same_class_test
720
722
 
721
723
  run_multiple_extensions_same_class_test:
722
724
  $(RUBY) test_multiple_extensions_same_class.rb
725
+ $(RUBY_CPPFLAGS)
723
726
  # Tell versions [3.59,3.63) of GNU make to not export all variables.
724
727
  # Otherwise a system limit (for SysV at least) may be exceeded.
725
728
  .NOEXPORT:
@@ -65,63 +65,64 @@ TESTCASE(non_default_constructor)
65
65
  ASSERT_EQUAL(42, o->i());
66
66
  }
67
67
 
68
- /*
69
68
  namespace
70
69
  {
70
+ int withArgsX;
71
+ float withArgsY;
72
+ bool withArgsYes;
73
+
71
74
  class WithDefaultArgs
72
75
  {
73
76
  public:
74
77
  WithDefaultArgs(int x, float y = 2.0, bool yes = false)
75
78
  {
76
- x_ = x;
77
- y_ = y;
78
- yes_ = yes;
79
+ withArgsX = x;
80
+ withArgsY = y;
81
+ withArgsYes = yes;
79
82
  }
83
+ };
80
84
 
81
- WithDefaultArgs(int x = 14) {
82
- x_ = x;
83
- y_ = 1.0;
84
- yes_ = false;
85
+ int withArgX;
86
+ class WithOneArg
87
+ {
88
+ public:
89
+ WithOneArg(int x = 14) {
90
+ withArgX = x;
85
91
  }
86
-
87
- int getX() { return x_; }
88
- float getY() { return y_; }
89
- bool getYes() { return yes_; }
90
-
91
- private:
92
-
93
- int x_;
94
- float y_;
95
- bool yes_;
96
92
  };
97
93
  }
98
94
 
99
95
  TESTCASE(constructor_supports_default_arguments)
100
96
  {
101
97
  Class klass = define_class<WithDefaultArgs>("WithDefaultArgs").
102
- define_constructor(Constructor<WithDefaultArgs, int, float, bool>(
103
- ( Arg("x"), Arg("y") = (float)2.0, Arg("yes") = (bool)false )));
104
-
105
- Data_Object<WithDefaultArgs> obj;
106
-
107
- obj= klass.call("new", 4);
108
- ASSERT_EQUAL(4, obj->getX());
109
- ASSERT_EQUAL(2.0, obj->getY());
110
- ASSERT_EQUAL(false, obj->getYes());
111
-
112
- obj= klass.call("new", 5, 3.0);
113
- ASSERT_EQUAL(5, obj->getX());
114
- ASSERT_EQUAL(3.0, obj->getY());
115
- ASSERT_EQUAL(false, obj->getYes());
116
-
117
- obj= klass.call("new", 7, 12.0, true);
118
- ASSERT_EQUAL(7, obj->getX());
119
- ASSERT_EQUAL(12.0, obj->getY());
120
- ASSERT_EQUAL(true, obj->getYes());
98
+ define_constructor(Constructor<WithDefaultArgs, int, float, bool>(),
99
+ ( Arg("x"), Arg("y") = (float)2.0, Arg("yes") = (bool)false ));
100
+
101
+ klass.call("new", 4);
102
+ ASSERT_EQUAL(4, withArgsX);
103
+ ASSERT_EQUAL(2.0, withArgsY);
104
+ ASSERT_EQUAL(false, withArgsYes);
105
+
106
+ klass.call("new", 5, 3.0);
107
+ ASSERT_EQUAL(5, withArgsX);
108
+ ASSERT_EQUAL(3.0, withArgsY);
109
+ ASSERT_EQUAL(false, withArgsYes);
110
+
111
+ klass.call("new", 7, 12.0, true);
112
+ ASSERT_EQUAL(7, withArgsX);
113
+ ASSERT_EQUAL(12.0, withArgsY);
114
+ ASSERT_EQUAL(true, withArgsYes);
121
115
  }
122
116
 
123
117
  TESTCASE(constructor_supports_single_default_argument)
124
118
  {
119
+ Class klass = define_class<WithOneArg>("WithOneArg").
120
+ define_constructor(Constructor<WithOneArg, int>(),
121
+ ( Arg("x") = 14 ));
122
+
123
+ klass.call("new");
124
+ ASSERT_EQUAL(14, withArgX);
125
125
 
126
+ klass.call("new", 6);
127
+ ASSERT_EQUAL(6, withArgX);
126
128
  }
127
- */
@@ -2,6 +2,7 @@
2
2
  #include "rice/Data_Type.hpp"
3
3
  #include "rice/Exception.hpp"
4
4
  #include "rice/Constructor.hpp"
5
+ #include "rice/global_function.hpp"
5
6
 
6
7
  using namespace Rice;
7
8
 
@@ -119,3 +120,229 @@ TESTCASE(no_super_in_constructor_still_works)
119
120
  ASSERT_EQUAL(INT2NUM(8), handler.call("process").value());
120
121
  }
121
122
  */
123
+
124
+ /**
125
+ * Implicit Casting across unrelated types
126
+ *
127
+ * Two ways of defining if types are implicitly castable
128
+ *
129
+ * 1) operator
130
+ * 2) constructor
131
+ */
132
+
133
+ /**
134
+ * Examples here taken from Ogre's Math library.
135
+ * This uses the constructor method of casting types.
136
+ */
137
+ namespace
138
+ {
139
+ const int degree2Radians = (3.14 / 180.0);
140
+ const int radian2Degrees = (180.0 / 3.14);
141
+
142
+ class Radian;
143
+
144
+ class Degree
145
+ {
146
+ public:
147
+ explicit Degree(float d) : val_(d) {}
148
+ Degree(const Radian& r);
149
+
150
+ float valueDegrees() const { return val_; }
151
+ float valueRadians() const { return val_ * degree2Radians; }
152
+
153
+ private:
154
+ float val_;
155
+ };
156
+
157
+ class Radian
158
+ {
159
+ public:
160
+ explicit Radian(float r) : val_(r) {}
161
+ Radian(const Degree& d) : val_(d.valueRadians()) {}
162
+
163
+ float valueRadians() const { return val_; }
164
+ float valueDegrees() const { return val_ * radian2Degrees; }
165
+
166
+ private:
167
+ float val_;
168
+ };
169
+
170
+ // Due to circular dependencies, need to define some
171
+ // methods down here
172
+ Degree::Degree(const Radian& r)
173
+ {
174
+ val_ = r.valueDegrees();
175
+ }
176
+
177
+ /**
178
+ * And now some methods that work w/ the above two classes
179
+ */
180
+ bool isAcute(Degree degree) {
181
+ return degree.valueDegrees() < 90;
182
+ }
183
+
184
+ bool isObtuse(Radian radian) {
185
+ return radian.valueDegrees() > 90 && radian.valueDegrees() <= 180;
186
+ }
187
+
188
+ bool isRight(Degree* degree) {
189
+ return degree->valueDegrees() == 90;
190
+ }
191
+ }
192
+
193
+ TESTCASE(can_define_implicit_type_conversions_across_wrapped_types)
194
+ {
195
+ define_class<Degree>("Degree")
196
+ .define_constructor(Constructor<Degree, float>());
197
+
198
+ define_class<Radian>("Radian")
199
+ .define_constructor(Constructor<Radian, float>());
200
+
201
+ define_implicit_cast<Degree, Radian>();
202
+ define_implicit_cast<Radian, Degree>();
203
+
204
+ define_global_function("is_acute", &isAcute);
205
+ define_global_function("is_obtuse", &isObtuse);
206
+ define_global_function("is_right", &isRight);
207
+
208
+ Module m = define_module("TestingModule");
209
+ Object result;
210
+
211
+ // ACUTE
212
+ result = m.instance_eval("is_acute(Degree.new(75))");
213
+ ASSERT(from_ruby<bool>(result.value()));
214
+
215
+ result = m.instance_eval("is_acute(Radian.new(2.0))");
216
+ ASSERT(!from_ruby<bool>(result.value()));
217
+
218
+ // OBTUSE
219
+ result = m.instance_eval("is_obtuse(Degree.new(75))");
220
+ ASSERT(!from_ruby<bool>(result.value()));
221
+
222
+ result = m.instance_eval("is_obtuse(Radian.new(2.0))");
223
+ ASSERT(from_ruby<bool>(result.value()));
224
+
225
+ // RIGHT
226
+ result = m.instance_eval("is_right(Degree.new(90))");
227
+ ASSERT(from_ruby<bool>(result.value()));
228
+
229
+ result = m.instance_eval("is_right(Radian.new(2.0))");
230
+ ASSERT(!from_ruby<bool>(result.value()));
231
+ }
232
+
233
+ namespace {
234
+ class Explicit
235
+ {
236
+ public:
237
+ Explicit(float v) {
238
+ value = v;
239
+ }
240
+
241
+ Explicit(const Degree &d) {
242
+ value = d.valueDegrees();
243
+ }
244
+
245
+ float getValue() { return value; }
246
+
247
+ private:
248
+ float value;
249
+ };
250
+
251
+ float getExplicitValue(Explicit* v) {
252
+ return v->getValue();
253
+ }
254
+ }
255
+
256
+ TESTCASE(supports_multiple_implicit_conversions_for_a_type)
257
+ {
258
+ define_class<Degree>("Degree")
259
+ .define_constructor(Constructor<Degree, float>());
260
+
261
+ define_class<Radian>("Radian")
262
+ .define_constructor(Constructor<Radian, float>());
263
+
264
+ define_class<Explicit>("Explicit")
265
+ .define_constructor(Constructor<Explicit, float>());
266
+
267
+ define_global_function("is_obtuse", &isObtuse);
268
+ define_global_function("explicit_value", &getExplicitValue);
269
+
270
+ define_implicit_cast<Radian, Degree>();
271
+ define_implicit_cast<Degree, Radian>();
272
+ define_implicit_cast<Degree, Explicit>();
273
+
274
+ Module m = define_module("TestingModule");
275
+ Object result;
276
+
277
+ result = m.instance_eval("is_obtuse(Degree.new(75))");
278
+ ASSERT(!from_ruby<bool>(result.value()));
279
+
280
+ result = m.instance_eval("explicit_value(Degree.new(75))");
281
+ ASSERT_EQUAL(75.0, from_ruby<float>(result.value()));
282
+ }
283
+
284
+ /**
285
+ * Sample taken and modified from boost::python::implicit:
286
+ * http://www.boost.org/doc/libs/1_41_0/libs/python/doc/v2/implicit.html
287
+ *
288
+ * This is the operator version of casting and shows that this works for
289
+ * base types as well as defined types
290
+ */
291
+ /*
292
+ namespace {
293
+ struct Real
294
+ {
295
+ Real(int x)
296
+ : v(x)
297
+ {}
298
+
299
+ operator int() const
300
+ {
301
+ return v;
302
+ }
303
+
304
+ int v;
305
+ };
306
+
307
+ int realValue(Real const& x)
308
+ {
309
+ return x.v;
310
+ }
311
+
312
+ Real makeReal(int n)
313
+ {
314
+ return Real(n);
315
+ }
316
+ }
317
+
318
+ TESTCASE(can_define_implicit_type_conversions_to_base_types)
319
+ {
320
+ define_class<Real>("Real")
321
+ .define_constructor(Constructor<Real, int>());
322
+
323
+ // Define the conversion rules
324
+ define_implicit_cast<Real, int>();
325
+ define_implicit_cast<int, Real>();
326
+
327
+ define_global_function("real_value", &realValue);
328
+ define_global_function("make_real", &makeReal);
329
+
330
+ Module m = define_module("TestingModule");
331
+
332
+ // As Real object
333
+ Object result = m.instance_eval("real_value( Real.new(4) )");
334
+ ASSERT_EQUAL(4, from_ruby<int>(result.value()));
335
+
336
+ // As fixnum (int)
337
+ result = m.instance_eval("real_value(4)");
338
+ ASSERT_EQUAL(4, from_ruby<int>(result.value()));
339
+
340
+ // As Real object
341
+ result = m.instance_eval("r = make_real( Real.new(6) ); real_value(r)");
342
+ ASSERT_EQUAL(6, from_ruby<int>(result.value()));
343
+
344
+ // As fixnum (int)
345
+ result = m.instance_eval("r = make_real(6); real_value(r)");
346
+ ASSERT_EQUAL(6, from_ruby<int>(result.value()));
347
+ }
348
+ */
@@ -0,0 +1,50 @@
1
+ #include "unittest.hpp"
2
+ #include "rice/String.hpp"
3
+ #include "rice/Class.hpp"
4
+ #include "rice/global_function.hpp"
5
+
6
+ using namespace Rice;
7
+
8
+ TESTSUITE(Memory_Management);
9
+
10
+ SETUP(Memory_Management)
11
+ {
12
+ ruby_init();
13
+ }
14
+
15
+ namespace
16
+ {
17
+ class TestClass {
18
+ double tmp;
19
+ public:
20
+ TestClass() {tmp=0;}
21
+
22
+ double getTmp() {
23
+ return tmp;
24
+ }
25
+
26
+ void setTmp(double x) {
27
+ tmp = x;
28
+ }
29
+ };
30
+
31
+ TestClass returnTestClass() {
32
+ TestClass x = TestClass();
33
+ x.setTmp(8);
34
+ return x;
35
+ }
36
+ }
37
+
38
+ TESTCASE(allows_copy_contructors_to_work)
39
+ {
40
+ define_class<TestClass>("TestClass")
41
+ .define_method("tmp=", &TestClass::setTmp)
42
+ .define_method("tmp", &TestClass::getTmp);
43
+
44
+ define_global_function("return_test_class", &returnTestClass);
45
+
46
+ Module m = define_module("TestingModule");
47
+
48
+ Object result = m.instance_eval("return_test_class.tmp");
49
+ ASSERT_EQUAL(8.0, from_ruby<double>(result.value()));
50
+ }
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 1
7
- - 3
8
- - 2
9
- version: 1.3.2
7
+ - 4
8
+ - 0
9
+ version: 1.4.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Paul Brannan
@@ -15,13 +15,14 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-05-06 00:00:00 -04:00
18
+ date: 2010-08-25 00:00:00 -04:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
22
  name: rubyforge
23
23
  prerelease: false
24
24
  requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
25
26
  requirements:
26
27
  - - ">="
27
28
  - !ruby/object:Gem::Version
@@ -230,6 +231,7 @@ files:
230
231
  - test/test_Hash.cpp
231
232
  - test/test_Identifier.cpp
232
233
  - test/test_Jump_Tag.cpp
234
+ - test/test_Memory_Management.cpp
233
235
  - test/test_Module.cpp
234
236
  - test/test_Object.cpp
235
237
  - test/test_String.cpp
@@ -246,6 +248,7 @@ files:
246
248
  - test/ext/t1/t1.cpp
247
249
  - test/ext/t2/extconf.rb
248
250
  - test/ext/t2/t2.cpp
251
+ - test/test_rice.rb
249
252
  has_rdoc: true
250
253
  homepage: http://rice.rubyforge.org/
251
254
  licenses: []
@@ -256,6 +259,7 @@ rdoc_options: []
256
259
  require_paths:
257
260
  - ruby/lib
258
261
  required_ruby_version: !ruby/object:Gem::Requirement
262
+ none: false
259
263
  requirements:
260
264
  - - ">="
261
265
  - !ruby/object:Gem::Version
@@ -263,6 +267,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
263
267
  - 0
264
268
  version: "0"
265
269
  required_rubygems_version: !ruby/object:Gem::Requirement
270
+ none: false
266
271
  requirements:
267
272
  - - ">="
268
273
  - !ruby/object:Gem::Version
@@ -272,7 +277,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
272
277
  requirements: []
273
278
 
274
279
  rubyforge_project: rice
275
- rubygems_version: 1.3.6
280
+ rubygems_version: 1.3.7
276
281
  signing_key:
277
282
  specification_version: 3
278
283
  summary: Ruby Interface for C++ Extensions