rice 4.0.4 → 4.2.0

Sign up to get free protection for your applications and to get access to all the features.
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
+ }