rice 4.0.4 → 4.2.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 (105) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +37 -0
  3. data/CONTRIBUTORS.md +2 -0
  4. data/Rakefile +1 -1
  5. data/include/rice/rice.hpp +2851 -1955
  6. data/include/rice/stl.hpp +1654 -287
  7. data/lib/mkmf-rice.rb +5 -2
  8. data/lib/version.rb +1 -1
  9. data/rice/Arg.hpp +6 -6
  10. data/rice/Arg.ipp +8 -9
  11. data/rice/Constructor.hpp +2 -2
  12. data/rice/Data_Object.ipp +69 -15
  13. data/rice/Data_Object_defn.hpp +1 -15
  14. data/rice/Data_Type.ipp +56 -86
  15. data/rice/Data_Type_defn.hpp +14 -17
  16. data/rice/Director.hpp +0 -1
  17. data/rice/Enum.ipp +31 -22
  18. data/rice/Exception.ipp +2 -3
  19. data/rice/Exception_defn.hpp +5 -5
  20. data/rice/HandlerRegistration.hpp +15 -0
  21. data/rice/Return.hpp +5 -4
  22. data/rice/Return.ipp +8 -3
  23. data/rice/detail/ExceptionHandler.hpp +8 -0
  24. data/rice/detail/ExceptionHandler.ipp +28 -0
  25. data/rice/detail/{Exception_Handler_defn.hpp → ExceptionHandler_defn.hpp} +17 -21
  26. data/rice/detail/HandlerRegistry.hpp +51 -0
  27. data/rice/detail/HandlerRegistry.ipp +20 -0
  28. data/rice/detail/InstanceRegistry.hpp +34 -0
  29. data/rice/detail/InstanceRegistry.ipp +50 -0
  30. data/rice/detail/MethodInfo.ipp +1 -1
  31. data/rice/detail/NativeAttribute.hpp +26 -15
  32. data/rice/detail/NativeAttribute.ipp +76 -47
  33. data/rice/detail/NativeFunction.hpp +64 -14
  34. data/rice/detail/NativeFunction.ipp +138 -86
  35. data/rice/detail/NativeIterator.hpp +49 -0
  36. data/rice/detail/NativeIterator.ipp +102 -0
  37. data/rice/detail/NativeRegistry.hpp +31 -0
  38. data/rice/detail/{method_data.ipp → NativeRegistry.ipp} +20 -16
  39. data/rice/detail/Registries.hpp +26 -0
  40. data/rice/detail/Registries.ipp +23 -0
  41. data/rice/detail/RubyFunction.hpp +6 -11
  42. data/rice/detail/RubyFunction.ipp +10 -22
  43. data/rice/detail/Type.hpp +1 -1
  44. data/rice/detail/Type.ipp +2 -2
  45. data/rice/detail/TypeRegistry.hpp +8 -11
  46. data/rice/detail/TypeRegistry.ipp +3 -28
  47. data/rice/detail/Wrapper.hpp +0 -2
  48. data/rice/detail/Wrapper.ipp +74 -24
  49. data/rice/detail/cpp_protect.hpp +93 -0
  50. data/rice/detail/default_allocation_func.ipp +1 -1
  51. data/rice/detail/from_ruby.ipp +206 -2
  52. data/rice/detail/to_ruby.ipp +39 -5
  53. data/rice/detail/to_ruby_defn.hpp +1 -1
  54. data/rice/forward_declares.ipp +6 -0
  55. data/rice/global_function.hpp +0 -4
  56. data/rice/global_function.ipp +0 -6
  57. data/rice/rice.hpp +29 -24
  58. data/rice/stl.hpp +6 -1
  59. data/sample/callbacks/extconf.rb +0 -1
  60. data/sample/enum/extconf.rb +0 -1
  61. data/sample/inheritance/extconf.rb +0 -1
  62. data/sample/map/extconf.rb +0 -1
  63. data/test/embed_ruby.cpp +6 -15
  64. data/test/ext/t1/extconf.rb +0 -1
  65. data/test/ext/t2/extconf.rb +0 -1
  66. data/test/extconf.rb +0 -1
  67. data/test/test_Array.cpp +20 -24
  68. data/test/test_Attribute.cpp +6 -6
  69. data/test/test_Class.cpp +8 -47
  70. data/test/test_Constructor.cpp +0 -2
  71. data/test/test_Data_Object.cpp +25 -11
  72. data/test/test_Data_Type.cpp +124 -28
  73. data/test/test_Director.cpp +12 -13
  74. data/test/test_Enum.cpp +65 -26
  75. data/test/test_Inheritance.cpp +9 -9
  76. data/test/test_Iterator.cpp +134 -5
  77. data/test/test_Keep_Alive.cpp +7 -7
  78. data/test/test_Keep_Alive_No_Wrapper.cpp +80 -0
  79. data/test/test_Memory_Management.cpp +1 -1
  80. data/test/test_Module.cpp +25 -62
  81. data/test/test_Object.cpp +75 -3
  82. data/test/test_Ownership.cpp +12 -13
  83. data/test/test_Self.cpp +12 -13
  84. data/test/test_Stl_Map.cpp +696 -0
  85. data/test/test_Stl_Optional.cpp +3 -3
  86. data/test/test_Stl_Pair.cpp +38 -2
  87. data/test/test_Stl_Reference_Wrapper.cpp +102 -0
  88. data/test/test_Stl_SmartPointer.cpp +49 -9
  89. data/test/test_Stl_String.cpp +5 -2
  90. data/test/test_Stl_Unordered_Map.cpp +697 -0
  91. data/test/test_Stl_Variant.cpp +346 -0
  92. data/test/test_Stl_Vector.cpp +200 -41
  93. data/test/test_Struct.cpp +3 -3
  94. data/test/test_To_From_Ruby.cpp +8 -2
  95. data/test/test_Tracking.cpp +239 -0
  96. data/test/unittest.hpp +21 -4
  97. metadata +24 -13
  98. data/rice/detail/Exception_Handler.hpp +0 -8
  99. data/rice/detail/Exception_Handler.ipp +0 -28
  100. data/rice/detail/Iterator.hpp +0 -23
  101. data/rice/detail/Iterator.ipp +0 -47
  102. data/rice/detail/function_traits.hpp +0 -124
  103. data/rice/detail/method_data.hpp +0 -29
  104. data/rice/detail/rice_traits.hpp +0 -116
  105. data/rice/ruby_try_catch.hpp +0 -86
@@ -0,0 +1,346 @@
1
+ #include "unittest.hpp"
2
+ #include "embed_ruby.hpp"
3
+ #include <rice/rice.hpp>
4
+ #include <rice/stl.hpp>
5
+
6
+ #include <variant>
7
+ #include <complex>
8
+
9
+ using namespace Rice;
10
+
11
+ TESTSUITE(Variant);
12
+
13
+ namespace
14
+ {
15
+ using Intrinsic_Variant_T = std::variant<
16
+ std::string,
17
+ std::complex<double>,
18
+ std::vector<int>,
19
+ double,
20
+ bool,
21
+ int
22
+ >;
23
+
24
+ inline std::ostream& operator<<(std::ostream& stream, Intrinsic_Variant_T const& variant)
25
+ {
26
+ stream << "Variant(" << "index: " << variant.index() << ")";
27
+ return stream;
28
+ }
29
+
30
+ class MyClass
31
+ {
32
+ public:
33
+ Intrinsic_Variant_T variantString()
34
+ {
35
+ // Need to tell compiler this is std::string and not a const char[8]. Because that
36
+ // becomes const char* which sets the boolean field to true. Oops. https://stackoverflow.com/a/44086312
37
+ Intrinsic_Variant_T result { std::string("a string") };
38
+ return result;
39
+ }
40
+
41
+ Intrinsic_Variant_T variantComplex()
42
+ {
43
+ using namespace std::complex_literals;
44
+ Intrinsic_Variant_T result { 1i };
45
+ return result;
46
+ }
47
+
48
+ Intrinsic_Variant_T variantVector()
49
+ {
50
+ Intrinsic_Variant_T result { std::vector<int>{1, 2, 3} };
51
+ return result;
52
+ }
53
+
54
+ Intrinsic_Variant_T variantDouble()
55
+ {
56
+ Intrinsic_Variant_T result { 3.3 };
57
+ return result;
58
+ }
59
+
60
+ Intrinsic_Variant_T variantBoolTrue()
61
+ {
62
+ Intrinsic_Variant_T result { true };
63
+ return result;
64
+ }
65
+
66
+ Intrinsic_Variant_T variantBoolFalse()
67
+ {
68
+ Intrinsic_Variant_T result{ false };
69
+ return result;
70
+ }
71
+
72
+ Intrinsic_Variant_T variantInt()
73
+ {
74
+ Intrinsic_Variant_T result { 5 };
75
+ return result;
76
+ }
77
+
78
+ Intrinsic_Variant_T variantRoundtrip(Intrinsic_Variant_T variant)
79
+ {
80
+ return variant;
81
+ }
82
+
83
+ Intrinsic_Variant_T variantRoundtripReference(Intrinsic_Variant_T variant)
84
+ {
85
+ return variant;
86
+ }
87
+
88
+ Intrinsic_Variant_T variant_ = std::string("Initial value");
89
+ };
90
+ }
91
+
92
+ void makeIntrinsicVariant()
93
+ {
94
+ define_class<MyClass>("MyClass").
95
+ define_constructor(Constructor<MyClass>()).
96
+ define_method("variant_string", &MyClass::variantString).
97
+ define_method("variant_complex", &MyClass::variantComplex).
98
+ define_method("variant_vector", &MyClass::variantVector).
99
+ define_method("variant_double", &MyClass::variantDouble).
100
+ define_method("variant_bool_true", &MyClass::variantBoolTrue).
101
+ define_method("variant_bool_false", &MyClass::variantBoolFalse).
102
+ define_method("variant_int", &MyClass::variantInt).
103
+ define_method("roundtrip", &MyClass::variantRoundtrip).
104
+ define_attr("variant_attr", &MyClass::variant_);
105
+ }
106
+
107
+ TESTCASE(IntrinsicReturns)
108
+ {
109
+ using namespace std::complex_literals;
110
+
111
+ Module m = define_module("Testing");
112
+ Object myClass = m.module_eval("MyClass.new");
113
+
114
+ Object result = myClass.call("variant_string");
115
+ ASSERT_EQUAL("a string", detail::From_Ruby<std::string>().convert(result));
116
+
117
+ result = myClass.call("variant_complex");
118
+ ASSERT_EQUAL(1i, detail::From_Ruby<std::complex<double>>().convert(result));
119
+
120
+ result = myClass.call("variant_vector");
121
+ std::vector<int> converted = detail::From_Ruby<std::vector<int>>().convert(result);
122
+ ASSERT_EQUAL(3, converted.size());
123
+
124
+ result = myClass.call("variant_double");
125
+ ASSERT_EQUAL(3.3, detail::From_Ruby<double>().convert(result));
126
+
127
+ result = myClass.call("variant_bool_true");
128
+ ASSERT(detail::From_Ruby<bool>().convert(result));
129
+
130
+ result = myClass.call("variant_bool_false");
131
+ ASSERT(!detail::From_Ruby<bool>().convert(result));
132
+
133
+ result = myClass.call("variant_int");
134
+ ASSERT_EQUAL(5, detail::From_Ruby<int>().convert(result));
135
+ }
136
+
137
+ TESTCASE(IntrinsicRoundtrip)
138
+ {
139
+ using namespace std::complex_literals;
140
+
141
+ Module m = define_module("Testing");
142
+ Object myClass = m.module_eval("MyClass.new");
143
+
144
+ std::string code = R"(my_class = MyClass.new
145
+ my_class.roundtrip("roundtrip string"))";
146
+ Object result = m.module_eval(code);
147
+ ASSERT_EQUAL("roundtrip string", detail::From_Ruby<std::string>().convert(result));
148
+
149
+ code = R"(my_class = MyClass.new
150
+ my_class.roundtrip(Complex(2, 3)))";
151
+ result = m.module_eval(code);
152
+ ASSERT_EQUAL((2.0 + 3i), detail::From_Ruby<std::complex<double>>().convert(result));
153
+
154
+ code = R"(my_class = MyClass.new
155
+ my_class.roundtrip([1, 2, 3]))";
156
+ result = m.module_eval(code);
157
+ std::vector<int> expected = {1, 2, 3};
158
+ ASSERT_EQUAL(expected, detail::From_Ruby<std::vector<int>>().convert(result));
159
+
160
+ code = R"(my_class = MyClass.new
161
+ my_class.roundtrip(44.4))";
162
+ result = m.module_eval(code);
163
+ ASSERT_EQUAL(44.4, detail::From_Ruby<double>().convert(result));
164
+
165
+ code = R"(my_class = MyClass.new
166
+ my_class.roundtrip(true))";
167
+ result = m.module_eval(code);
168
+ ASSERT(detail::From_Ruby<bool>().convert(result));
169
+
170
+ code = R"(my_class = MyClass.new
171
+ my_class.roundtrip(false))";
172
+ result = m.module_eval(code);
173
+ ASSERT(!detail::From_Ruby<bool>().convert(result));
174
+
175
+ code = R"(my_class = MyClass.new
176
+ my_class.roundtrip(45))";
177
+ result = m.module_eval(code);
178
+ ASSERT_EQUAL(45, detail::From_Ruby<int>().convert(result));
179
+ }
180
+
181
+ TESTCASE(VariantAttribute)
182
+ {
183
+ Module m = define_module("Testing");
184
+ Object myClass = m.module_eval("MyClass.new");
185
+
186
+ Object result = myClass.call("variant_attr");
187
+ ASSERT_EQUAL("Initial value", detail::From_Ruby<std::string>().convert(result));
188
+
189
+ result = myClass.call("variant_attr=", "Second value");
190
+ ASSERT_EQUAL("Second value", detail::From_Ruby<std::string>().convert(result));
191
+ result = myClass.call("variant_attr");
192
+ ASSERT_EQUAL("Second value", detail::From_Ruby<std::string>().convert(result));
193
+
194
+ result = myClass.call("variant_attr=", 77.7);
195
+ ASSERT_EQUAL(77.7, detail::From_Ruby<double>().convert(result));
196
+ result = myClass.call("variant_attr");
197
+ ASSERT_EQUAL(77.7, detail::From_Ruby<double>().convert(result));
198
+
199
+ result = myClass.call("variant_attr=", true);
200
+ ASSERT(detail::From_Ruby<bool>().convert(result));
201
+ result = myClass.call("variant_attr");
202
+ ASSERT(detail::From_Ruby<bool>().convert(result));
203
+
204
+ result = myClass.call("variant_attr=", false);
205
+ ASSERT(!detail::From_Ruby<bool>().convert(result));
206
+ result = myClass.call("variant_attr");
207
+ ASSERT(!detail::From_Ruby<bool>().convert(result));
208
+
209
+ result = myClass.call("variant_attr=", 78);
210
+ ASSERT_EQUAL(78, detail::From_Ruby<int>().convert(result));
211
+ result = myClass.call("variant_attr");
212
+ ASSERT_EQUAL(78, detail::From_Ruby<int>().convert(result));
213
+ }
214
+
215
+ namespace
216
+ {
217
+ class MyClass1
218
+ {
219
+ public:
220
+ MyClass1()
221
+ {
222
+ int a = 1;
223
+ }
224
+
225
+ std::string sayHello()
226
+ {
227
+ return "Hi from MyClass1";
228
+ }
229
+ };
230
+
231
+ class MyClass2
232
+ {
233
+ public:
234
+ MyClass2()
235
+ {
236
+ int a = 2;
237
+ }
238
+
239
+ std::string sayHello()
240
+ {
241
+ return "Hi from MyClass2";
242
+ }
243
+ };
244
+
245
+ using Class_Variant_T = std::variant<std::monostate, MyClass1, MyClass2>;
246
+
247
+ Class_Variant_T variantClass(bool myClass1)
248
+ {
249
+ if (myClass1)
250
+ {
251
+ return MyClass1();
252
+ }
253
+ else
254
+ {
255
+ return MyClass2();
256
+ }
257
+ }
258
+
259
+ Class_Variant_T roundTripVariantClass(Class_Variant_T variant)
260
+ {
261
+ return variant;
262
+ }
263
+
264
+ Class_Variant_T& roundTripVariantClassRef(Class_Variant_T& variant)
265
+ {
266
+ return variant;
267
+ }
268
+ }
269
+
270
+ void makeClassVariant()
271
+ {
272
+ define_class<MyClass1>("MyClass1").
273
+ define_constructor(Constructor<MyClass1>()).
274
+ define_method("say_hello", &MyClass1::sayHello);
275
+
276
+ define_class<MyClass2>("MyClass2").
277
+ define_constructor(Constructor<MyClass2>()).
278
+ define_method("say_hello", &MyClass2::sayHello);
279
+
280
+ define_global_function("variant_class", &variantClass);
281
+ define_global_function("roundtrip_variant_class", &roundTripVariantClass);
282
+ define_global_function("roundtrip_variant_class_ref", &roundTripVariantClassRef);
283
+ }
284
+
285
+ SETUP(Variant)
286
+ {
287
+ embed_ruby();
288
+ makeIntrinsicVariant();
289
+ makeClassVariant();
290
+ }
291
+
292
+ TESTCASE(ClassReturns)
293
+ {
294
+ Module m = define_module("Testing");
295
+
296
+ Data_Object<MyClass1> myclass1 = m.module_eval("variant_class(true)");
297
+ String hello = myclass1.call("say_hello");
298
+ ASSERT_EQUAL("Hi from MyClass1", detail::From_Ruby<std::string>().convert(hello));
299
+
300
+ Data_Object<MyClass2> myclass2 = m.module_eval("variant_class(false)");
301
+ hello = myclass2.call("say_hello");
302
+ ASSERT_EQUAL("Hi from MyClass2", detail::From_Ruby<std::string>().convert(hello));
303
+ }
304
+
305
+ TESTCASE(ClassRoundtrip)
306
+ {
307
+ Module m = define_module("Testing");
308
+
309
+ Object instance = m.module_eval("MyClass1.new");
310
+ Object instance2 = m.call("roundtrip_variant_class", instance);
311
+ String hello = instance2.call("say_hello");
312
+ ASSERT_EQUAL("Hi from MyClass1", detail::From_Ruby<std::string>().convert(hello));
313
+
314
+ instance = m.module_eval("MyClass2.new");
315
+ instance2 = m.call("roundtrip_variant_class", instance);
316
+ hello = instance2.call("say_hello");
317
+ ASSERT_EQUAL("Hi from MyClass2", detail::From_Ruby<std::string>().convert(hello));
318
+ }
319
+
320
+ /* This test case runs successfully on MSVC but not g++. Having stepped through the code with
321
+ GDB, this sure seems due to a bug with g++. The issue is this variable in created operator():
322
+
323
+ Arg_Ts nativeValues = this->getNativeValues(rubyValues, indices);
324
+
325
+ And is then passed to invokeNativeFunction as a const Arg_Ts& nativeArgs where Arg_Ts& is
326
+ std::tuple with one element, a reference to a variant. So it doesn't change and the address
327
+ of the variable doesn't change. But for some reason g++ resets the
328
+ the std::variant index to 0 thus breaking the test. Maybe something to do with storing
329
+ a refernence to a variant in a tuple? */
330
+
331
+ #ifdef _MSC_VER
332
+ TESTCASE(ClassRoundtripRef)
333
+ {
334
+ Module m = define_module("Testing");
335
+
336
+ Object instance = m.module_eval("MyClass1.new");
337
+ Object instance2 = m.call("roundtrip_variant_class_ref", instance);
338
+ String hello = instance2.call("say_hello");
339
+ ASSERT_EQUAL("Hi from MyClass1", detail::From_Ruby<std::string>().convert(hello));
340
+
341
+ instance = m.module_eval("MyClass2.new");
342
+ instance2 = m.call("roundtrip_variant_class_ref", instance);
343
+ hello = instance2.call("say_hello");
344
+ ASSERT_EQUAL("Hi from MyClass2", detail::From_Ruby<std::string>().convert(hello));
345
+ }
346
+ #endif
@@ -1,5 +1,4 @@
1
1
  #include <complex>
2
- #include <memory>
3
2
 
4
3
  #include "unittest.hpp"
5
4
  #include "embed_ruby.hpp"
@@ -31,7 +30,7 @@ namespace
31
30
 
32
31
  Class makeVectorClass()
33
32
  {
34
- Class c= define_class<MyClass>("MyClass").
33
+ Class c = define_class<MyClass>("MyClass").
35
34
  define_constructor(Constructor<MyClass>()).
36
35
  define_method("stringVector", &MyClass::stringVector);
37
36
 
@@ -44,15 +43,15 @@ TESTCASE(StringVector)
44
43
 
45
44
  Class c = define_vector<std::vector<std::string>>("StringVector");
46
45
 
47
- Object vec = m.instance_eval("$vector = StringVector.new");
46
+ Object vec = m.module_eval("$vector = StringVector.new");
48
47
  Object result = vec.call("size");
49
48
  ASSERT_EQUAL(0, detail::From_Ruby<int32_t>().convert(result));
50
49
 
51
- m.instance_eval("$vector << 'one' << 'two' << 'two' << 'three'");
50
+ m.module_eval("$vector << 'one' << 'two' << 'two' << 'three'");
52
51
  result = vec.call("size");
53
52
  ASSERT_EQUAL(4, detail::From_Ruby<int32_t>().convert(result));
54
53
 
55
- m.instance_eval("$vector.append('four')");
54
+ m.module_eval("$vector.append('four')");
56
55
  result = vec.call("size");
57
56
  ASSERT_EQUAL(5, detail::From_Ruby<int32_t>().convert(result));
58
57
 
@@ -69,10 +68,10 @@ TESTCASE(WrongType)
69
68
 
70
69
  Class c = define_vector<std::vector<std::string>>("StringVector");
71
70
 
72
- Object vec = m.instance_eval("$vector = StringVector.new");
71
+ Object vec = m.module_eval("$vector = StringVector.new");
73
72
  ASSERT_EXCEPTION_CHECK(
74
73
  Exception,
75
- m.instance_eval("$vector << 1"),
74
+ m.module_eval("$vector << 1"),
76
75
  ASSERT_EQUAL("wrong argument type Integer (expected String)", ex.what()));
77
76
  }
78
77
 
@@ -261,24 +260,6 @@ TESTCASE(Copy)
261
260
  ASSERT_NOT_EQUAL(vec.size(), vecCopy.size());
262
261
  }
263
262
 
264
- TESTCASE(Iterate)
265
- {
266
- Module m = define_module("Testing");
267
- Class c = define_vector<std::vector<double>>("DoubleVector");
268
-
269
- std::string code = R"(vector = DoubleVector.new
270
- vector << 5.0 << 6.0 << 7.0
271
- updated = vector.map do |value|
272
- value * 2.0
273
- end)";
274
-
275
- Array result = m.instance_eval(code);
276
- ASSERT_EQUAL(3, result.size());
277
- ASSERT_EQUAL(10.0, detail::From_Ruby<double>().convert(result[0].value()));
278
- ASSERT_EQUAL(12.0, detail::From_Ruby<double>().convert(result[1].value()));
279
- ASSERT_EQUAL(14.0, detail::From_Ruby<double>().convert(result[2].value()));
280
- }
281
-
282
263
  namespace
283
264
  {
284
265
  class NotComparable
@@ -308,7 +289,7 @@ TESTCASE(NotComparable)
308
289
  ASSERT_EQUAL(Qnil, result.value());
309
290
 
310
291
  result = vec.call("length");
311
- ASSERT_EQUAL(3, detail::From_Ruby<size_t>().convert(result));
292
+ ASSERT_EQUAL(3u, detail::From_Ruby<size_t>().convert(result));
312
293
 
313
294
  result = vec.call("include?", NotComparable(2));
314
295
  ASSERT_EQUAL(Qfalse, result.value());
@@ -437,13 +418,13 @@ TESTCASE(Printable)
437
418
 
438
419
  namespace
439
420
  {
440
- std::vector<std::complex<uint32_t>> returnComplexVector()
421
+ std::vector<std::complex<double>> returnComplexVector()
441
422
  {
442
- std::complex<uint32_t> complex1(1, 1);
443
- std::complex<uint32_t> complex2(2, 2);
444
- std::complex<uint32_t> complex3(3, 3);
423
+ std::complex<double> complex1(1, 1);
424
+ std::complex<double> complex2(2, 2);
425
+ std::complex<double> complex3(3, 3);
445
426
 
446
- std::vector<std::complex<uint32_t>> result;
427
+ std::vector<std::complex<double>> result;
447
428
  result.push_back(complex1);
448
429
  result.push_back(complex2);
449
430
  result.push_back(complex3);
@@ -461,15 +442,27 @@ TESTCASE(AutoRegisterReturn)
461
442
  define_global_function("return_complex_vector", &returnComplexVector);
462
443
 
463
444
  Module m = define_module("Testing");
464
- Object vec = m.instance_eval("return_complex_vector");
465
- ASSERT_EQUAL("Rice::Std::Vector__complex__unsignedInt___allocator__complex__unsignedInt______", vec.class_name().str());
445
+ Object vec = m.module_eval("return_complex_vector");
446
+ ASSERT_EQUAL("Rice::Std::Vector__complex__double___allocator__complex__double______", vec.class_name().str());
466
447
 
467
448
  std::string code = R"(vector = return_complex_vector
468
449
  complex = vector.last
469
450
  complex == Complex(3, 3))";
470
451
 
471
- Object result = m.instance_eval(code);
452
+ Object result = m.module_eval(code);
472
453
  ASSERT_EQUAL(Qtrue, result.value());
454
+
455
+ // Now register this same vector
456
+ define_vector<std::vector<std::complex<double>>>("ComplexVector");
457
+ code = R"(vector = ComplexVector.new)";
458
+ result = m.module_eval(code);
459
+ ASSERT(result.is_instance_of(vec.class_of()));
460
+
461
+ // Now register it again in the module
462
+ define_vector_under<std::vector<std::complex<double>>>(m, "ComplexVector2");
463
+ code = R"(vector = Testing::ComplexVector2.new)";
464
+ result = m.module_eval(code);
465
+ ASSERT(result.is_instance_of(vec.class_of()));
473
466
  }
474
467
 
475
468
  TESTCASE(AutoRegisterParameter)
@@ -482,7 +475,7 @@ TESTCASE(AutoRegisterParameter)
482
475
  pass_complex_vector(vector))";
483
476
 
484
477
  Module m = define_module("Testing");
485
- Object vec = m.instance_eval(code);
478
+ Object vec = m.module_eval(code);
486
479
 
487
480
  Object result = vec.call("size");
488
481
  ASSERT_EQUAL("Rice::Std::Vector__complex__double___allocator__complex__double______", vec.class_name().str());
@@ -507,7 +500,7 @@ TESTCASE(DefaultValue)
507
500
  define_global_function("default_vector", &defaultVector, Arg("strings") = std::vector<std::string> { "one", "two", "three" });
508
501
 
509
502
  Module m = define_module("Testing");
510
- Object result = m.instance_eval("default_vector");
503
+ Object result = m.module_eval("default_vector");
511
504
  std::vector<std::string> actual = detail::From_Ruby<std::vector<std::string>>().convert(result);
512
505
 
513
506
  std::vector<std::string> expected{ "one", "two", "three" };
@@ -518,6 +511,27 @@ TESTCASE(DefaultValue)
518
511
  ASSERT_EQUAL(expected[2], actual[2]);
519
512
  }
520
513
 
514
+ TESTCASE(ToArray)
515
+ {
516
+ Module m = define_module("Testing");
517
+
518
+ Class c = define_vector<std::vector<std::string>>("StringVector").
519
+ define_constructor(Constructor<std::vector<std::string>>());
520
+
521
+ std::string code = R"(vector = StringVector.new
522
+ vector << "abc"
523
+ vector << "def"
524
+ vector << "ghi"
525
+ vector.to_a)";
526
+
527
+ Array array = m.module_eval(code);
528
+ ASSERT_EQUAL(3u, array.size());
529
+
530
+ ASSERT_EQUAL("abc", detail::From_Ruby<std::string>().convert(array[0].value()));
531
+ ASSERT_EQUAL("def", detail::From_Ruby<std::string>().convert(array[1].value()));
532
+ ASSERT_EQUAL("ghi", detail::From_Ruby<std::string>().convert(array[2].value()));
533
+ }
534
+
521
535
  namespace
522
536
  {
523
537
  std::vector<int> ints;
@@ -553,7 +567,7 @@ TESTCASE(ArrayToVector)
553
567
  Module m = define_module("Testing");
554
568
 
555
569
  std::string code = "array_to_vector([7, 9, 1_000_000], [49.0, 78.0, 999.0], %w[one two three])";
556
- m.instance_eval(code);
570
+ m.module_eval(code);
557
571
 
558
572
  ASSERT_EQUAL(3, ints.size());
559
573
  ASSERT_EQUAL(7, ints[0]);
@@ -578,7 +592,7 @@ TESTCASE(ArrayToVectorRefs)
578
592
  Module m = define_module("Testing");
579
593
 
580
594
  std::string code = "array_to_vector_refs([8, 10, 1_000_001], [50.0, 79.0, 1_000.0], %w[eleven twelve thirteen])";
581
- m.instance_eval(code);
595
+ m.module_eval(code);
582
596
 
583
597
  ASSERT_EQUAL(3, ints.size());
584
598
  ASSERT_EQUAL(8, ints[0]);
@@ -603,7 +617,7 @@ TESTCASE(ArrayToVectorPointers)
603
617
  Module m = define_module("Testing");
604
618
 
605
619
  std::string code = "array_to_vector_pointers([9, 11, 1_000_002], [51.0, 80.0, 1_001.0], %w[fourteen fifteen sixteen])";
606
- m.instance_eval(code);
620
+ m.module_eval(code);
607
621
 
608
622
  ASSERT_EQUAL(3, ints.size());
609
623
  ASSERT_EQUAL(9, ints[0]);
@@ -631,7 +645,7 @@ TESTCASE(ArrayToVectorWrongTypes)
631
645
 
632
646
  ASSERT_EXCEPTION_CHECK(
633
647
  Exception,
634
- m.instance_eval(code),
648
+ m.module_eval(code),
635
649
  ASSERT_EQUAL("wrong argument type Float (expected String)", ex.what())
636
650
  );
637
651
  }
@@ -646,7 +660,152 @@ TESTCASE(ArrayToVectorMixedTypes)
646
660
 
647
661
  ASSERT_EXCEPTION_CHECK(
648
662
  Exception,
649
- m.instance_eval(code),
663
+ m.module_eval(code),
650
664
  ASSERT_EQUAL("no implicit conversion of String into Integer", ex.what())
651
665
  );
652
666
  }
667
+
668
+ namespace
669
+ {
670
+ class Factory
671
+ {
672
+ public:
673
+ std::vector<std::string>* returnPointer()
674
+ {
675
+ return &this->instance_;
676
+ }
677
+
678
+ std::vector<std::string>& returnReference()
679
+ {
680
+ return this->instance_;
681
+ }
682
+
683
+ std::vector<std::string> returnValue()
684
+ {
685
+ return this->instance_;
686
+ }
687
+
688
+ public:
689
+ static inline std::vector<std::string> instance_{ "one", "two", "three" };
690
+ };
691
+
692
+ std::ostream& operator<<(std::ostream& stream, const std::vector<std::string>& vector)
693
+ {
694
+ stream << "Vector";
695
+ return stream;
696
+ }
697
+ }
698
+
699
+ void createFactoryClass()
700
+ {
701
+ define_class<Factory>("Factory").
702
+ define_constructor(Constructor<Factory>()).
703
+ define_method("pointer", &Factory::returnPointer).
704
+ define_method("reference", &Factory::returnReference).
705
+ define_method("value", &Factory::returnValue);
706
+ }
707
+
708
+ TESTCASE(Returns)
709
+ {
710
+ createFactoryClass();
711
+ Module m = define_module("TestingModule");
712
+ Object factory = m.module_eval("Factory.new");
713
+
714
+ std::vector<std::string> expected{ "one", "two", "three" };
715
+
716
+ Data_Object<std::vector<std::string>> vec1 = factory.call("pointer");
717
+ ASSERT_EQUAL(expected, *vec1);
718
+
719
+ Data_Object<std::vector<std::string>> vec2 = factory.call("reference");
720
+ ASSERT_EQUAL(expected, *vec2);
721
+
722
+ Data_Object<std::vector<std::string>> vec3 = factory.call("value");
723
+ ASSERT_EQUAL(expected, *vec3);
724
+ }
725
+
726
+ TESTCASE(Iterate)
727
+ {
728
+ Module m = define_module("Testing");
729
+ Class c = define_vector<std::vector<double>>("DoubleVector");
730
+
731
+ std::string code = R"(vector = DoubleVector.new
732
+ vector << 5.0 << 6.0 << 7.0
733
+ updated = vector.map do |value|
734
+ value * 2.0
735
+ end)";
736
+
737
+ Array result = m.module_eval(code);
738
+ ASSERT_EQUAL(3, result.size());
739
+ ASSERT_EQUAL(10.0, detail::From_Ruby<double>().convert(result[0].value()));
740
+ ASSERT_EQUAL(12.0, detail::From_Ruby<double>().convert(result[1].value()));
741
+ ASSERT_EQUAL(14.0, detail::From_Ruby<double>().convert(result[2].value()));
742
+ }
743
+
744
+ TESTCASE(ToEnumPointer)
745
+ {
746
+ createFactoryClass();
747
+ Module m = define_module("TestingModule");
748
+
749
+ std::string code = R"(factory = Factory.new
750
+ vector = factory.pointer
751
+ updated = vector.each.map do |value|
752
+ value + "_updated"
753
+ end)";
754
+
755
+ Array result = m.module_eval(code);
756
+
757
+ ASSERT_EQUAL(3, result.size());
758
+ ASSERT_EQUAL("one_updated", detail::From_Ruby<std::string>().convert(result[0].value()));
759
+ ASSERT_EQUAL("two_updated", detail::From_Ruby<std::string>().convert(result[1].value()));
760
+ ASSERT_EQUAL("three_updated", detail::From_Ruby<std::string>().convert(result[2].value()));
761
+ }
762
+
763
+ TESTCASE(ToEnumReference)
764
+ {
765
+ createFactoryClass();
766
+ Module m = define_module("TestingModule");
767
+
768
+ std::string code = R"(factory = Factory.new
769
+ vector = factory.reference
770
+ updated = vector.each.map do |value|
771
+ value + "_updated"
772
+ end)";
773
+
774
+ Array result = m.module_eval(code);
775
+
776
+ ASSERT_EQUAL(3, result.size());
777
+ ASSERT_EQUAL("one_updated", detail::From_Ruby<std::string>().convert(result[0].value()));
778
+ ASSERT_EQUAL("two_updated", detail::From_Ruby<std::string>().convert(result[1].value()));
779
+ ASSERT_EQUAL("three_updated", detail::From_Ruby<std::string>().convert(result[2].value()));
780
+ }
781
+
782
+ TESTCASE(ToEnumValue)
783
+ {
784
+ createFactoryClass();
785
+ Module m = define_module("TestingModule");
786
+
787
+ std::string code = R"(factory = Factory.new
788
+ vector = factory.value
789
+ updated = vector.each.map do |value|
790
+ value + "_updated"
791
+ end)";
792
+
793
+ Array result = m.module_eval(code);
794
+
795
+ ASSERT_EQUAL(3, result.size());
796
+ ASSERT_EQUAL("one_updated", detail::From_Ruby<std::string>().convert(result[0].value()));
797
+ ASSERT_EQUAL("two_updated", detail::From_Ruby<std::string>().convert(result[1].value()));
798
+ ASSERT_EQUAL("three_updated", detail::From_Ruby<std::string>().convert(result[2].value()));
799
+ }
800
+
801
+ TESTCASE(ToEnumSize)
802
+ {
803
+ createFactoryClass();
804
+ Module m = define_module("TestingModule");
805
+ Object factory = m.module_eval("Factory.new");
806
+ Object vector = factory.call("pointer");
807
+ Object enumerable = vector.call("each");
808
+ Object result = enumerable.call("size");
809
+
810
+ ASSERT_EQUAL(3, detail::From_Ruby<int>().convert(result));
811
+ }