rice 4.3.2 → 4.5.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 (151) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +66 -25
  3. data/README.md +7 -2
  4. data/Rakefile +7 -1
  5. data/include/rice/rice.hpp +7321 -4470
  6. data/include/rice/stl.hpp +769 -222
  7. data/lib/mkmf-rice.rb +37 -95
  8. data/rice/Address_Registration_Guard.hpp +72 -3
  9. data/rice/Arg.hpp +19 -5
  10. data/rice/Arg.ipp +24 -0
  11. data/rice/Callback.hpp +21 -0
  12. data/rice/Callback.ipp +13 -0
  13. data/rice/Constructor.hpp +4 -27
  14. data/rice/Constructor.ipp +79 -0
  15. data/rice/Data_Object.hpp +74 -3
  16. data/rice/Data_Object.ipp +324 -32
  17. data/rice/Data_Type.hpp +215 -3
  18. data/rice/Data_Type.ipp +125 -64
  19. data/rice/Director.hpp +0 -2
  20. data/rice/Enum.hpp +4 -6
  21. data/rice/Enum.ipp +101 -57
  22. data/rice/Exception.hpp +62 -2
  23. data/rice/Exception.ipp +7 -12
  24. data/rice/JumpException.hpp +44 -0
  25. data/rice/JumpException.ipp +48 -0
  26. data/rice/MemoryView.hpp +11 -0
  27. data/rice/MemoryView.ipp +43 -0
  28. data/rice/Return.hpp +6 -26
  29. data/rice/Return.ipp +10 -16
  30. data/rice/detail/DefaultHandler.hpp +12 -0
  31. data/rice/detail/DefaultHandler.ipp +8 -0
  32. data/rice/detail/HandlerRegistry.hpp +5 -35
  33. data/rice/detail/HandlerRegistry.ipp +7 -11
  34. data/rice/detail/InstanceRegistry.hpp +1 -4
  35. data/rice/detail/MethodInfo.hpp +15 -5
  36. data/rice/detail/MethodInfo.ipp +78 -6
  37. data/rice/detail/Native.hpp +32 -0
  38. data/rice/detail/Native.ipp +129 -0
  39. data/rice/detail/NativeAttributeGet.hpp +51 -0
  40. data/rice/detail/NativeAttributeGet.ipp +51 -0
  41. data/rice/detail/NativeAttributeSet.hpp +43 -0
  42. data/rice/detail/NativeAttributeSet.ipp +82 -0
  43. data/rice/detail/NativeCallbackFFI.hpp +55 -0
  44. data/rice/detail/NativeCallbackFFI.ipp +151 -0
  45. data/rice/detail/NativeCallbackSimple.hpp +30 -0
  46. data/rice/detail/NativeCallbackSimple.ipp +29 -0
  47. data/rice/detail/NativeFunction.hpp +20 -21
  48. data/rice/detail/NativeFunction.ipp +199 -64
  49. data/rice/detail/NativeIterator.hpp +8 -11
  50. data/rice/detail/NativeIterator.ipp +27 -31
  51. data/rice/detail/NativeRegistry.hpp +24 -17
  52. data/rice/detail/NativeRegistry.ipp +23 -56
  53. data/rice/detail/Proc.hpp +4 -0
  54. data/rice/detail/Proc.ipp +85 -0
  55. data/rice/detail/Registries.hpp +0 -7
  56. data/rice/detail/Registries.ipp +0 -18
  57. data/rice/detail/RubyFunction.hpp +0 -3
  58. data/rice/detail/RubyFunction.ipp +4 -8
  59. data/rice/detail/RubyType.hpp +19 -0
  60. data/rice/detail/RubyType.ipp +187 -0
  61. data/rice/detail/TupleIterator.hpp +14 -0
  62. data/rice/detail/Type.hpp +5 -6
  63. data/rice/detail/Type.ipp +150 -33
  64. data/rice/detail/TypeRegistry.hpp +15 -7
  65. data/rice/detail/TypeRegistry.ipp +105 -12
  66. data/rice/detail/Wrapper.hpp +6 -5
  67. data/rice/detail/Wrapper.ipp +45 -23
  68. data/rice/detail/cpp_protect.hpp +5 -6
  69. data/rice/detail/default_allocation_func.ipp +0 -2
  70. data/rice/detail/from_ruby.hpp +37 -3
  71. data/rice/detail/from_ruby.ipp +911 -454
  72. data/rice/detail/ruby.hpp +18 -0
  73. data/rice/detail/to_ruby.hpp +41 -3
  74. data/rice/detail/to_ruby.ipp +437 -113
  75. data/rice/global_function.hpp +0 -4
  76. data/rice/global_function.ipp +1 -2
  77. data/rice/rice.hpp +105 -22
  78. data/rice/ruby_mark.hpp +4 -3
  79. data/rice/stl.hpp +4 -0
  80. data/test/embed_ruby.cpp +4 -1
  81. data/test/extconf.rb +2 -0
  82. data/test/ruby/test_multiple_extensions_same_class.rb +14 -14
  83. data/test/test_Address_Registration_Guard.cpp +5 -0
  84. data/test/test_Array.cpp +12 -1
  85. data/test/test_Attribute.cpp +103 -21
  86. data/test/test_Builtin_Object.cpp +5 -0
  87. data/test/test_Callback.cpp +231 -0
  88. data/test/test_Class.cpp +5 -31
  89. data/test/test_Constructor.cpp +69 -6
  90. data/test/test_Data_Object.cpp +9 -4
  91. data/test/test_Data_Type.cpp +428 -64
  92. data/test/test_Director.cpp +10 -5
  93. data/test/test_Enum.cpp +152 -40
  94. data/test/test_Exception.cpp +235 -0
  95. data/test/test_File.cpp +70 -0
  96. data/test/test_From_Ruby.cpp +542 -0
  97. data/test/test_Hash.cpp +5 -0
  98. data/test/test_Identifier.cpp +5 -0
  99. data/test/test_Inheritance.cpp +6 -1
  100. data/test/test_Iterator.cpp +5 -0
  101. data/test/test_JumpException.cpp +22 -0
  102. data/test/test_Keep_Alive.cpp +6 -1
  103. data/test/test_Keep_Alive_No_Wrapper.cpp +5 -0
  104. data/test/test_Memory_Management.cpp +5 -0
  105. data/test/test_Module.cpp +118 -64
  106. data/test/test_Native_Registry.cpp +2 -33
  107. data/test/test_Object.cpp +5 -0
  108. data/test/test_Overloads.cpp +631 -0
  109. data/test/test_Ownership.cpp +67 -4
  110. data/test/test_Proc.cpp +45 -0
  111. data/test/test_Self.cpp +5 -0
  112. data/test/test_Stl_Exception.cpp +109 -0
  113. data/test/test_Stl_Map.cpp +22 -8
  114. data/test/test_Stl_Optional.cpp +5 -0
  115. data/test/test_Stl_Pair.cpp +7 -2
  116. data/test/test_Stl_Reference_Wrapper.cpp +5 -0
  117. data/test/test_Stl_SmartPointer.cpp +210 -5
  118. data/test/test_Stl_String.cpp +5 -0
  119. data/test/test_Stl_String_View.cpp +5 -0
  120. data/test/test_Stl_Type.cpp +147 -0
  121. data/test/test_Stl_Unordered_Map.cpp +18 -7
  122. data/test/test_Stl_Variant.cpp +5 -0
  123. data/test/test_Stl_Vector.cpp +130 -8
  124. data/test/test_String.cpp +5 -0
  125. data/test/test_Struct.cpp +5 -0
  126. data/test/test_Symbol.cpp +5 -0
  127. data/test/test_Template.cpp +192 -0
  128. data/test/test_To_Ruby.cpp +152 -0
  129. data/test/test_Tracking.cpp +1 -0
  130. data/test/test_Type.cpp +100 -0
  131. data/test/test_global_functions.cpp +53 -6
  132. data/test/unittest.cpp +8 -0
  133. metadata +37 -20
  134. data/lib/version.rb +0 -3
  135. data/rice/Address_Registration_Guard_defn.hpp +0 -79
  136. data/rice/Data_Object_defn.hpp +0 -84
  137. data/rice/Data_Type_defn.hpp +0 -190
  138. data/rice/Exception_defn.hpp +0 -68
  139. data/rice/HandlerRegistration.hpp +0 -15
  140. data/rice/Identifier.hpp +0 -50
  141. data/rice/Identifier.ipp +0 -29
  142. data/rice/detail/ExceptionHandler.hpp +0 -8
  143. data/rice/detail/ExceptionHandler.ipp +0 -28
  144. data/rice/detail/ExceptionHandler_defn.hpp +0 -77
  145. data/rice/detail/Jump_Tag.hpp +0 -21
  146. data/rice/detail/NativeAttribute.hpp +0 -64
  147. data/rice/detail/NativeAttribute.ipp +0 -112
  148. data/rice/detail/from_ruby_defn.hpp +0 -38
  149. data/rice/detail/to_ruby_defn.hpp +0 -48
  150. data/test/test_Jump_Tag.cpp +0 -17
  151. data/test/test_To_From_Ruby.cpp +0 -399
@@ -74,7 +74,7 @@ namespace
74
74
  }
75
75
 
76
76
  public:
77
- MyClass* transferPointer()
77
+ MyClass* transferPointerToRuby()
78
78
  {
79
79
  return new MyClass();
80
80
  }
@@ -99,6 +99,11 @@ namespace
99
99
  return std::move(MyClass());
100
100
  }
101
101
 
102
+ void transferPointerToCpp(MyClass* myClass)
103
+ {
104
+ delete myClass;
105
+ }
106
+
102
107
  MyClass* instance()
103
108
  {
104
109
  if (!instance_)
@@ -118,6 +123,7 @@ SETUP(Ownership)
118
123
  embed_ruby();
119
124
 
120
125
  define_class<MyClass>("MyClass").
126
+ define_constructor(Constructor<MyClass>()).
121
127
  define_method("process", &MyClass::process).
122
128
  define_method("set_flag", &MyClass::setFlag);
123
129
 
@@ -125,13 +131,19 @@ SETUP(Ownership)
125
131
  define_constructor(Constructor<Factory>()).
126
132
  define_method("value", &Factory::value).
127
133
  define_method("move_value", &Factory::moveValue).
128
- define_method("transfer_pointer", &Factory::transferPointer, Return().takeOwnership()).
134
+ define_method("transfer_pointer_to_ruby", &Factory::transferPointerToRuby, Return().takeOwnership()).
135
+ define_method("transfer_pointer_to_cpp", &Factory::transferPointerToCpp, Arg("myClass").takeOwnership()).
129
136
  define_method("keep_pointer", &Factory::keepPointer).
130
137
  define_method("copy_reference", &Factory::keepReference, Return().takeOwnership()).
131
138
  define_method("keep_reference", &Factory::keepReference);
132
139
  }
133
140
 
134
- TESTCASE(TransferPointer)
141
+ TEARDOWN(Ownership)
142
+ {
143
+ rb_gc_start();
144
+ }
145
+
146
+ TESTCASE(TransferPointerToRuby)
135
147
  {
136
148
  Factory::reset();
137
149
  MyClass::reset();
@@ -140,7 +152,7 @@ TESTCASE(TransferPointer)
140
152
 
141
153
  std::string code = R"(factory = Factory.new
142
154
  10.times do |i|
143
- my_class = factory.transfer_pointer
155
+ my_class = factory.transfer_pointer_to_ruby
144
156
  my_class.set_flag(i)
145
157
  my_class = nil
146
158
  end)";
@@ -155,6 +167,23 @@ TESTCASE(TransferPointer)
155
167
  ASSERT(!Factory::instance_);
156
168
  }
157
169
 
170
+ TESTCASE(TransferPointerToCpp)
171
+ {
172
+ Factory::reset();
173
+ MyClass::reset();
174
+
175
+ Module m = define_module("TestingModule");
176
+
177
+ std::string code = R"(myClass = MyClass.new
178
+ factory = Factory.new
179
+ factory.transfer_pointer_to_cpp(myClass))";
180
+
181
+ m.module_eval(code);
182
+ rb_gc_start();
183
+
184
+ ASSERT(true);
185
+ }
186
+
158
187
  TESTCASE(KeepPointer)
159
188
  {
160
189
  Factory::reset();
@@ -272,3 +301,37 @@ TESTCASE(MoveValue)
272
301
  ASSERT_EQUAL(30, MyClass::destructorCalls);
273
302
  ASSERT(!Factory::instance_);
274
303
  }
304
+
305
+ namespace
306
+ {
307
+ class MyClassNotCopyable
308
+ {
309
+ public:
310
+ MyClassNotCopyable() = default;
311
+ MyClassNotCopyable(const MyClassNotCopyable& other) = delete;
312
+ MyClassNotCopyable(MyClassNotCopyable&& other) = delete;
313
+ int value;
314
+ };
315
+ }
316
+
317
+ TESTCASE(NotCopyable)
318
+ {
319
+ Class c = define_class<MyClassNotCopyable>("MyClassNotCopyable")
320
+ .define_constructor(Constructor<MyClassNotCopyable>())
321
+ .define_attr("value", &MyClassNotCopyable::value);
322
+
323
+ MyClassNotCopyable instance;
324
+
325
+ #ifdef _MSC_VER
326
+ const char* expected = "Ruby was directed to take ownership of a C++ object but it does not have an accessible copy or move constructor. Type: class `anonymous namespace'::MyClassNotCopyable";
327
+ #else
328
+ const char* expected = "Ruby was directed to take ownership of a C++ object but it does not have an accessible copy or move constructor. Type: (anonymous namespace)::MyClassNotCopyable";
329
+ #endif
330
+
331
+ // Trying to take ownership should fail
332
+ ASSERT_EXCEPTION_CHECK(
333
+ std::runtime_error,
334
+ Data_Object<MyClassNotCopyable>(instance, true),
335
+ ASSERT_EQUAL(expected, ex.what())
336
+ );
337
+ }
@@ -0,0 +1,45 @@
1
+ #include <functional>
2
+
3
+ #include "unittest.hpp"
4
+ #include "embed_ruby.hpp"
5
+ #include <rice/rice.hpp>
6
+ #include <rice/stl.hpp>
7
+
8
+ using namespace Rice;
9
+
10
+ TESTSUITE(Proc);
11
+
12
+ SETUP(Proc)
13
+ {
14
+ embed_ruby();
15
+ }
16
+
17
+ TEARDOWN(Proc)
18
+ {
19
+ rb_gc_start();
20
+ }
21
+
22
+ namespace
23
+ {
24
+ int square(int i)
25
+ {
26
+ return i * i;
27
+ }
28
+
29
+ auto squareProc()
30
+ {
31
+ return square;
32
+ }
33
+ }
34
+
35
+ TESTCASE(SquareProc)
36
+ {
37
+ Module m = define_module("TestingModuleMakeProc");
38
+ m.define_module_function("square_proc", squareProc);
39
+
40
+ std::string code = R"(proc = square_proc
41
+ proc.call(9))";
42
+
43
+ Object result = m.module_eval(code);
44
+ ASSERT_EQUAL(81, detail::From_Ruby<int>().convert(result));
45
+ }
data/test/test_Self.cpp CHANGED
@@ -89,6 +89,11 @@ SETUP(Self)
89
89
  });
90
90
  }
91
91
 
92
+ TEARDOWN(Self)
93
+ {
94
+ rb_gc_start();
95
+ }
96
+
92
97
  TESTCASE(SelfPointer)
93
98
  {
94
99
  SelfClass::reset();
@@ -0,0 +1,109 @@
1
+ #include <complex>
2
+ #include <memory>
3
+
4
+ #include "unittest.hpp"
5
+ #include "embed_ruby.hpp"
6
+ #include <rice/rice.hpp>
7
+ #include <rice/stl.hpp>
8
+
9
+ using namespace Rice;
10
+
11
+ TESTSUITE(StlException);
12
+
13
+ SETUP(StlException)
14
+ {
15
+ embed_ruby();
16
+ }
17
+
18
+ TEARDOWN(StlException)
19
+ {
20
+ rb_gc_start();
21
+ }
22
+
23
+ namespace
24
+ {
25
+ class MyException: public std::exception
26
+ {
27
+ };
28
+
29
+ void raiseMyException()
30
+ {
31
+ throw MyException();
32
+ }
33
+
34
+ }
35
+
36
+ TESTCASE(StlExceptionCreate)
37
+ {
38
+ Class MyExceptionKlass = define_class<MyException, std::exception>("MyException");
39
+
40
+ auto handler = [MyExceptionKlass]()
41
+ {
42
+ try
43
+ {
44
+ throw;
45
+ }
46
+ catch (const MyException& exception)
47
+ {
48
+ Data_Object<MyException> wrapper(exception, true);
49
+ rb_exc_raise(wrapper.value());
50
+ }
51
+ };
52
+ detail::Registries::instance.handlers.set(handler);
53
+
54
+ Module m = define_module("Testing");
55
+ m.define_singleton_function("raise_my_exception", &raiseMyException);
56
+
57
+ std::string code = R"(begin
58
+ raise_my_exception
59
+ rescue MyException => exception
60
+ $!
61
+ end)";
62
+
63
+ Object object = m.instance_eval(code);
64
+ ASSERT_EQUAL(MyExceptionKlass.value(), object.class_of().value());
65
+ }
66
+
67
+ namespace
68
+ {
69
+ std::exception_ptr createExceptionPtr()
70
+ {
71
+ std::exception_ptr eptr;
72
+
73
+ try
74
+ {
75
+ [[maybe_unused]]
76
+ char ch = std::string().at(1); // this generates a std::out_of_range
77
+ }
78
+ catch (...)
79
+ {
80
+ eptr = std::current_exception(); // capture
81
+ }
82
+
83
+ return eptr;
84
+ }
85
+
86
+ void handleExceptionPtr(std::exception_ptr eptr)
87
+ {
88
+ std::rethrow_exception(eptr);
89
+ }
90
+ }
91
+
92
+ TESTCASE(StlExceptionPtr)
93
+ {
94
+ Module m = define_module("TestingModule");
95
+ m.define_module_function("create_exception_ptr", createExceptionPtr).
96
+ define_module_function("handle_exception_ptr", handleExceptionPtr);
97
+
98
+ Data_Object<std::exception_ptr> exception = m.call("create_exception_ptr");
99
+ VALUE value = exception.value();
100
+ std::exception_ptr* ptr = exception.get();
101
+ ASSERT((value != Qnil));
102
+ ASSERT((ptr != nullptr));
103
+
104
+ ASSERT_EXCEPTION_CHECK(
105
+ Exception,
106
+ m.call("handle_exception_ptr", exception),
107
+ ASSERT_EQUAL(rb_eIndexError, ex.class_of())
108
+ );
109
+ }
@@ -1,10 +1,11 @@
1
- #include <complex>
1
+ #include <complex>
2
2
  #include <memory>
3
3
 
4
4
  #include "unittest.hpp"
5
5
  #include "embed_ruby.hpp"
6
6
  #include <rice/rice.hpp>
7
7
  #include <rice/stl.hpp>
8
+ #include <ruby/version.h>
8
9
 
9
10
  using namespace Rice;
10
11
 
@@ -15,9 +16,13 @@ SETUP(Map)
15
16
  embed_ruby();
16
17
  }
17
18
 
18
- namespace
19
+ TEARDOWN(Map)
19
20
  {
21
+ rb_gc_start();
22
+ }
20
23
 
24
+ namespace
25
+ {
21
26
  class MyClass
22
27
  {
23
28
  public:
@@ -253,7 +258,11 @@ TESTCASE(Iterate)
253
258
  ASSERT_EQUAL(3u, result.size());
254
259
 
255
260
  std::string result_string = result.to_s().str();
261
+ #if RUBY_API_VERSION_MAJOR == 3 && RUBY_API_VERSION_MINOR >= 4
262
+ ASSERT_EQUAL("{\"five\" => 10, \"seven\" => 14, \"six\" => 12}", result_string);
263
+ #else
256
264
  ASSERT_EQUAL("{\"five\"=>10, \"seven\"=>14, \"six\"=>12}", result_string);
265
+ #endif
257
266
  }
258
267
 
259
268
  TESTCASE(ToEnum)
@@ -276,7 +285,12 @@ TESTCASE(ToEnum)
276
285
  ASSERT_EQUAL(3u, result.size());
277
286
 
278
287
  std::string result_string = result.to_s().str();
288
+
289
+ #if RUBY_API_VERSION_MAJOR == 3 && RUBY_API_VERSION_MINOR >= 4
290
+ ASSERT_EQUAL("{\"five\" => 10, \"seven\" => 14, \"six\" => 12}", result_string);
291
+ #else
279
292
  ASSERT_EQUAL("{\"five\"=>10, \"seven\"=>14, \"six\"=>12}", result_string);
293
+ #endif
280
294
  }
281
295
 
282
296
  TESTCASE(ToEnumSize)
@@ -433,7 +447,7 @@ TESTCASE(AutoRegisterReturn)
433
447
 
434
448
  Module m = define_module("Testing");
435
449
  Object map = m.module_eval("return_complex_map");
436
- ASSERT_EQUAL("Rice::Std::Map__basic_string__char_char_traits__char___allocator__char_____complex__double___less__basic_string__char_char_traits__char___allocator__char_______allocator__pair__basic_string__char_char_traits__char___allocator__char____Const_complex__double________",
450
+ ASSERT_EQUAL(u8"Rice::Std::Map≺string≺char≻‚ complex≺double≻≻",
437
451
  map.class_name().str());
438
452
 
439
453
  std::string code = R"(map = return_complex_map
@@ -460,16 +474,16 @@ TESTCASE(AutoRegisterParameter)
460
474
  {
461
475
  define_global_function("pass_complex_map", &passComplexMap);
462
476
 
463
- std::string code = R"(map = Rice::Std::Map__basic_string__char_char_traits__char___allocator__char_____complex__double___less__basic_string__char_char_traits__char___allocator__char_______allocator__pair__basic_string__char_char_traits__char___allocator__char____Const_complex__double________.new
464
- map["four"] = Complex(4.0, 4.0)
465
- map["five"] = Complex(5.0, 5.0)
466
- pass_complex_map(map))";
477
+ std::string code = u8R"(map = Rice::Std::Map≺string≺char≻‚ complex≺double≻≻.new
478
+ map["four"] = Complex(4.0, 4.0)
479
+ map["five"] = Complex(5.0, 5.0)
480
+ pass_complex_map(map))";
467
481
 
468
482
  Module m = define_module("Testing");
469
483
  Object map = m.module_eval(code);
470
484
 
471
485
  Object result = map.call("size");
472
- ASSERT_EQUAL("Rice::Std::Map__basic_string__char_char_traits__char___allocator__char_____complex__double___less__basic_string__char_char_traits__char___allocator__char_______allocator__pair__basic_string__char_char_traits__char___allocator__char____Const_complex__double________",
486
+ ASSERT_EQUAL(u8"Rice::Std::Map≺string≺char≻‚ complex≺double≻≻",
473
487
  map.class_name().str());
474
488
  ASSERT_EQUAL(2, detail::From_Ruby<int32_t>().convert(result));
475
489
 
@@ -50,6 +50,11 @@ SETUP(Optional)
50
50
  makeOptionalClass();
51
51
  }
52
52
 
53
+ TEARDOWN(Optional)
54
+ {
55
+ rb_gc_start();
56
+ }
57
+
53
58
  TESTCASE(OptionalReturn)
54
59
  {
55
60
  Module m = define_module("Testing");
@@ -1,4 +1,4 @@
1
- #include <utility>
1
+ #include <utility>
2
2
 
3
3
  #include "unittest.hpp"
4
4
  #include "embed_ruby.hpp"
@@ -14,6 +14,11 @@ SETUP(Pair)
14
14
  embed_ruby();
15
15
  }
16
16
 
17
+ TEARDOWN(Pair)
18
+ {
19
+ rb_gc_start();
20
+ }
21
+
17
22
  TESTCASE(CreatePair)
18
23
  {
19
24
  Module m = define_module("Testing");
@@ -102,7 +107,7 @@ TESTCASE(AutoRegister)
102
107
 
103
108
  Object pair = someClass.call("pair");
104
109
  String name = pair.class_name();
105
- ASSERT_EQUAL("Rice::Std::Pair__basic_string__char_char_traits__char___allocator__char_____double__", detail::From_Ruby<std::string>().convert(name));
110
+ ASSERT_EQUAL(u8"Rice::Std::Pair≺string≺char≻‚ double≻", detail::From_Ruby<std::string>().convert(name));
106
111
 
107
112
  Class pairKlass1 = pair.class_of();
108
113
  Class pairKlass2 = Data_Type<std::pair<std::string, double>>::klass();
@@ -61,6 +61,11 @@ SETUP(ReferenceWrapper)
61
61
  makeReferenceWrapperClass();
62
62
  }
63
63
 
64
+ TEARDOWN(ReferenceWrapper)
65
+ {
66
+ rb_gc_start();
67
+ }
68
+
64
69
  TESTCASE(Return)
65
70
  {
66
71
  Module m = define_module("Testing");