rice 4.0.3 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +30 -0
  3. data/Rakefile +1 -1
  4. data/include/rice/rice.hpp +2597 -1771
  5. data/include/rice/stl.hpp +1580 -271
  6. data/lib/mkmf-rice.rb +5 -2
  7. data/lib/version.rb +1 -1
  8. data/rice/Arg.hpp +6 -6
  9. data/rice/Arg.ipp +8 -9
  10. data/rice/Constructor.hpp +2 -2
  11. data/rice/Data_Object.ipp +69 -15
  12. data/rice/Data_Object_defn.hpp +1 -15
  13. data/rice/Data_Type.ipp +56 -86
  14. data/rice/Data_Type_defn.hpp +14 -17
  15. data/rice/Director.hpp +0 -1
  16. data/rice/Enum.ipp +31 -22
  17. data/rice/Exception.ipp +2 -3
  18. data/rice/Exception_defn.hpp +5 -5
  19. data/rice/HandlerRegistration.hpp +15 -0
  20. data/rice/Return.hpp +5 -4
  21. data/rice/Return.ipp +8 -3
  22. data/rice/detail/ExceptionHandler.hpp +8 -0
  23. data/rice/detail/ExceptionHandler.ipp +28 -0
  24. data/rice/detail/{Exception_Handler_defn.hpp → ExceptionHandler_defn.hpp} +17 -21
  25. data/rice/detail/HandlerRegistry.hpp +51 -0
  26. data/rice/detail/HandlerRegistry.ipp +20 -0
  27. data/rice/detail/InstanceRegistry.hpp +34 -0
  28. data/rice/detail/InstanceRegistry.ipp +50 -0
  29. data/rice/detail/MethodInfo.ipp +1 -1
  30. data/rice/detail/NativeAttribute.hpp +26 -15
  31. data/rice/detail/NativeAttribute.ipp +76 -47
  32. data/rice/detail/NativeFunction.hpp +60 -13
  33. data/rice/detail/NativeFunction.ipp +103 -85
  34. data/rice/detail/NativeIterator.hpp +49 -0
  35. data/rice/detail/NativeIterator.ipp +102 -0
  36. data/rice/detail/NativeRegistry.hpp +31 -0
  37. data/rice/detail/{method_data.ipp → NativeRegistry.ipp} +20 -16
  38. data/rice/detail/Registries.hpp +26 -0
  39. data/rice/detail/Registries.ipp +23 -0
  40. data/rice/detail/RubyFunction.hpp +6 -11
  41. data/rice/detail/RubyFunction.ipp +10 -22
  42. data/rice/detail/Type.hpp +1 -1
  43. data/rice/detail/Type.ipp +3 -2
  44. data/rice/detail/TypeRegistry.hpp +8 -11
  45. data/rice/detail/TypeRegistry.ipp +3 -28
  46. data/rice/detail/Wrapper.hpp +0 -2
  47. data/rice/detail/Wrapper.ipp +73 -23
  48. data/rice/detail/cpp_protect.hpp +93 -0
  49. data/rice/detail/default_allocation_func.ipp +1 -1
  50. data/rice/detail/from_ruby.ipp +206 -2
  51. data/rice/detail/to_ruby.ipp +39 -5
  52. data/rice/detail/to_ruby_defn.hpp +1 -1
  53. data/rice/forward_declares.ipp +6 -0
  54. data/rice/global_function.hpp +0 -4
  55. data/rice/global_function.ipp +0 -6
  56. data/rice/rice.hpp +29 -24
  57. data/rice/stl.hpp +6 -1
  58. data/test/embed_ruby.cpp +0 -14
  59. data/test/test_Array.cpp +20 -24
  60. data/test/test_Class.cpp +8 -47
  61. data/test/test_Constructor.cpp +0 -2
  62. data/test/test_Data_Object.cpp +25 -11
  63. data/test/test_Data_Type.cpp +124 -28
  64. data/test/test_Director.cpp +12 -13
  65. data/test/test_Enum.cpp +65 -26
  66. data/test/test_Inheritance.cpp +9 -9
  67. data/test/test_Iterator.cpp +134 -5
  68. data/test/test_Keep_Alive.cpp +7 -7
  69. data/test/test_Memory_Management.cpp +1 -1
  70. data/test/test_Module.cpp +25 -62
  71. data/test/test_Object.cpp +66 -3
  72. data/test/test_Ownership.cpp +12 -13
  73. data/test/test_Self.cpp +12 -13
  74. data/test/test_Stl_Map.cpp +696 -0
  75. data/test/test_Stl_Optional.cpp +3 -3
  76. data/test/test_Stl_Pair.cpp +38 -2
  77. data/test/test_Stl_Reference_Wrapper.cpp +102 -0
  78. data/test/test_Stl_SmartPointer.cpp +5 -5
  79. data/test/test_Stl_Unordered_Map.cpp +697 -0
  80. data/test/test_Stl_Variant.cpp +301 -0
  81. data/test/test_Stl_Vector.cpp +200 -41
  82. data/test/test_Struct.cpp +3 -3
  83. data/test/test_To_From_Ruby.cpp +6 -0
  84. data/test/test_Tracking.cpp +239 -0
  85. data/test/unittest.hpp +13 -4
  86. metadata +23 -13
  87. data/rice/detail/Exception_Handler.hpp +0 -8
  88. data/rice/detail/Exception_Handler.ipp +0 -28
  89. data/rice/detail/Iterator.hpp +0 -23
  90. data/rice/detail/Iterator.ipp +0 -47
  91. data/rice/detail/function_traits.hpp +0 -124
  92. data/rice/detail/method_data.hpp +0 -29
  93. data/rice/detail/rice_traits.hpp +0 -116
  94. data/rice/ruby_try_catch.hpp +0 -86
@@ -0,0 +1,301 @@
1
+ #include "unittest.hpp"
2
+ #include "embed_ruby.hpp"
3
+ #include <rice/rice.hpp>
4
+ #include <rice/stl.hpp>
5
+
6
+ #include <variant>
7
+
8
+ using namespace Rice;
9
+
10
+ TESTSUITE(Variant);
11
+
12
+ namespace
13
+ {
14
+ using Intrinsic_Variant_T = std::variant<std::string, double, bool, int>;
15
+
16
+ inline std::ostream& operator<<(std::ostream& stream, Intrinsic_Variant_T const& variant)
17
+ {
18
+ stream << "Variant(" << "index: " << variant.index() << ")";
19
+ return stream;
20
+ }
21
+
22
+ class MyClass
23
+ {
24
+ public:
25
+ Intrinsic_Variant_T variantString()
26
+ {
27
+ // Need to tell compiler this is std::string and not a const char[8]. Because that
28
+ // becomes const char* which sets the boolean field to true. Oops. https://stackoverflow.com/a/44086312
29
+ Intrinsic_Variant_T result { std::string("a string") };
30
+ return result;
31
+ }
32
+
33
+ Intrinsic_Variant_T variantDouble()
34
+ {
35
+ Intrinsic_Variant_T result { 3.3 };
36
+ return result;
37
+ }
38
+
39
+ Intrinsic_Variant_T variantBoolTrue()
40
+ {
41
+ Intrinsic_Variant_T result { true };
42
+ return result;
43
+ }
44
+
45
+ Intrinsic_Variant_T variantBoolFalse()
46
+ {
47
+ Intrinsic_Variant_T result{ false };
48
+ return result;
49
+ }
50
+
51
+ Intrinsic_Variant_T variantInt()
52
+ {
53
+ Intrinsic_Variant_T result { 5 };
54
+ return result;
55
+ }
56
+
57
+ Intrinsic_Variant_T variantRoundtrip(Intrinsic_Variant_T variant)
58
+ {
59
+ return variant;
60
+ }
61
+
62
+ Intrinsic_Variant_T variantRoundtripReference(Intrinsic_Variant_T variant)
63
+ {
64
+ return variant;
65
+ }
66
+
67
+ Intrinsic_Variant_T variant_ = std::string("Initial value");
68
+ };
69
+ }
70
+
71
+ void makeIntrinsicVariant()
72
+ {
73
+ define_class<MyClass>("MyClass").
74
+ define_constructor(Constructor<MyClass>()).
75
+ define_method("variant_string", &MyClass::variantString).
76
+ define_method("variant_double", &MyClass::variantDouble).
77
+ define_method("variant_bool_true", &MyClass::variantBoolTrue).
78
+ define_method("variant_bool_false", &MyClass::variantBoolFalse).
79
+ define_method("variant_int", &MyClass::variantInt).
80
+ define_method("roundtrip", &MyClass::variantRoundtrip).
81
+ define_attr("variant_attr", &MyClass::variant_);
82
+ }
83
+
84
+ TESTCASE(IntrinsicReturns)
85
+ {
86
+ Module m = define_module("Testing");
87
+ Object myClass = m.module_eval("MyClass.new");
88
+
89
+ Object result = myClass.call("variant_string");
90
+ ASSERT_EQUAL("a string", detail::From_Ruby<std::string>().convert(result));
91
+
92
+ result = myClass.call("variant_double");
93
+ ASSERT_EQUAL(3.3, detail::From_Ruby<double>().convert(result));
94
+
95
+ result = myClass.call("variant_bool_true");
96
+ ASSERT(detail::From_Ruby<bool>().convert(result));
97
+
98
+ result = myClass.call("variant_bool_false");
99
+ ASSERT(!detail::From_Ruby<bool>().convert(result));
100
+
101
+ result = myClass.call("variant_int");
102
+ ASSERT_EQUAL(5, detail::From_Ruby<int>().convert(result));
103
+ }
104
+
105
+ TESTCASE(IntrinsicRoundtrip)
106
+ {
107
+ Module m = define_module("Testing");
108
+ Object myClass = m.module_eval("MyClass.new");
109
+
110
+ std::string code = R"(my_class = MyClass.new
111
+ my_class.roundtrip("roundtrip string"))";
112
+ Object result = m.module_eval(code);
113
+ ASSERT_EQUAL("roundtrip string", detail::From_Ruby<std::string>().convert(result));
114
+
115
+ code = R"(my_class = MyClass.new
116
+ my_class.roundtrip(44.4))";
117
+ result = m.module_eval(code);
118
+ ASSERT_EQUAL(44.4, detail::From_Ruby<double>().convert(result));
119
+
120
+ code = R"(my_class = MyClass.new
121
+ my_class.roundtrip(true))";
122
+ result = m.module_eval(code);
123
+ ASSERT(detail::From_Ruby<bool>().convert(result));
124
+
125
+ code = R"(my_class = MyClass.new
126
+ my_class.roundtrip(false))";
127
+ result = m.module_eval(code);
128
+ ASSERT(!detail::From_Ruby<bool>().convert(result));
129
+
130
+ code = R"(my_class = MyClass.new
131
+ my_class.roundtrip(45))";
132
+ result = m.module_eval(code);
133
+ ASSERT_EQUAL(45, detail::From_Ruby<int>().convert(result));
134
+ }
135
+
136
+ TESTCASE(VariantAttribute)
137
+ {
138
+ Module m = define_module("Testing");
139
+ Object myClass = m.module_eval("MyClass.new");
140
+
141
+ Object result = myClass.call("variant_attr");
142
+ ASSERT_EQUAL("Initial value", detail::From_Ruby<std::string>().convert(result));
143
+
144
+ result = myClass.call("variant_attr=", "Second value");
145
+ ASSERT_EQUAL("Second value", detail::From_Ruby<std::string>().convert(result));
146
+ result = myClass.call("variant_attr");
147
+ ASSERT_EQUAL("Second value", detail::From_Ruby<std::string>().convert(result));
148
+
149
+ result = myClass.call("variant_attr=", 77.7);
150
+ ASSERT_EQUAL(77.7, detail::From_Ruby<double>().convert(result));
151
+ result = myClass.call("variant_attr");
152
+ ASSERT_EQUAL(77.7, detail::From_Ruby<double>().convert(result));
153
+
154
+ result = myClass.call("variant_attr=", true);
155
+ ASSERT(detail::From_Ruby<bool>().convert(result));
156
+ result = myClass.call("variant_attr");
157
+ ASSERT(detail::From_Ruby<bool>().convert(result));
158
+
159
+ result = myClass.call("variant_attr=", false);
160
+ ASSERT(!detail::From_Ruby<bool>().convert(result));
161
+ result = myClass.call("variant_attr");
162
+ ASSERT(!detail::From_Ruby<bool>().convert(result));
163
+
164
+ result = myClass.call("variant_attr=", 78);
165
+ ASSERT_EQUAL(78, detail::From_Ruby<int>().convert(result));
166
+ result = myClass.call("variant_attr");
167
+ ASSERT_EQUAL(78, detail::From_Ruby<int>().convert(result));
168
+ }
169
+
170
+ namespace
171
+ {
172
+ class MyClass1
173
+ {
174
+ public:
175
+ MyClass1()
176
+ {
177
+ int a = 1;
178
+ }
179
+
180
+ std::string sayHello()
181
+ {
182
+ return "Hi from MyClass1";
183
+ }
184
+ };
185
+
186
+ class MyClass2
187
+ {
188
+ public:
189
+ MyClass2()
190
+ {
191
+ int a = 2;
192
+ }
193
+
194
+ std::string sayHello()
195
+ {
196
+ return "Hi from MyClass2";
197
+ }
198
+ };
199
+
200
+ using Class_Variant_T = std::variant<std::monostate, MyClass1, MyClass2>;
201
+
202
+ Class_Variant_T variantClass(bool myClass1)
203
+ {
204
+ if (myClass1)
205
+ {
206
+ return MyClass1();
207
+ }
208
+ else
209
+ {
210
+ return MyClass2();
211
+ }
212
+ }
213
+
214
+ Class_Variant_T roundTripVariantClass(Class_Variant_T variant)
215
+ {
216
+ return variant;
217
+ }
218
+
219
+ Class_Variant_T& roundTripVariantClassRef(Class_Variant_T& variant)
220
+ {
221
+ return variant;
222
+ }
223
+ }
224
+
225
+ void makeClassVariant()
226
+ {
227
+ define_class<MyClass1>("MyClass1").
228
+ define_constructor(Constructor<MyClass1>()).
229
+ define_method("say_hello", &MyClass1::sayHello);
230
+
231
+ define_class<MyClass2>("MyClass2").
232
+ define_constructor(Constructor<MyClass2>()).
233
+ define_method("say_hello", &MyClass2::sayHello);
234
+
235
+ define_global_function("variant_class", &variantClass);
236
+ define_global_function("roundtrip_variant_class", &roundTripVariantClass);
237
+ define_global_function("roundtrip_variant_class_ref", &roundTripVariantClassRef);
238
+ }
239
+
240
+ SETUP(Variant)
241
+ {
242
+ embed_ruby();
243
+ makeIntrinsicVariant();
244
+ makeClassVariant();
245
+ }
246
+
247
+ TESTCASE(ClassReturns)
248
+ {
249
+ Module m = define_module("Testing");
250
+
251
+ Data_Object<MyClass1> myclass1 = m.module_eval("variant_class(true)");
252
+ String hello = myclass1.call("say_hello");
253
+ ASSERT_EQUAL("Hi from MyClass1", detail::From_Ruby<std::string>().convert(hello));
254
+
255
+ Data_Object<MyClass2> myclass2 = m.module_eval("variant_class(false)");
256
+ hello = myclass2.call("say_hello");
257
+ ASSERT_EQUAL("Hi from MyClass2", detail::From_Ruby<std::string>().convert(hello));
258
+ }
259
+
260
+ TESTCASE(ClassRoundtrip)
261
+ {
262
+ Module m = define_module("Testing");
263
+
264
+ Object instance = m.module_eval("MyClass1.new");
265
+ Object instance2 = m.call("roundtrip_variant_class", instance);
266
+ String hello = instance2.call("say_hello");
267
+ ASSERT_EQUAL("Hi from MyClass1", detail::From_Ruby<std::string>().convert(hello));
268
+
269
+ instance = m.module_eval("MyClass2.new");
270
+ instance2 = m.call("roundtrip_variant_class", instance);
271
+ hello = instance2.call("say_hello");
272
+ ASSERT_EQUAL("Hi from MyClass2", detail::From_Ruby<std::string>().convert(hello));
273
+ }
274
+
275
+ /* This test case runs successfully on MSVC but not g++. Having stepped through the code with
276
+ GDB, this sure seems due to a bug with g++. The issue is this variable in created operator():
277
+
278
+ Arg_Ts nativeValues = this->getNativeValues(rubyValues, indices);
279
+
280
+ And is then passed to invokeNativeFunction as a const Arg_Ts& nativeArgs where Arg_Ts& is
281
+ std::tuple with one element, a reference to a variant. So it doesn't change and the address
282
+ of the variable doesn't change. But for some reason g++ resets the
283
+ the std::variant index to 0 thus breaking the test. Maybe something to do with storing
284
+ a refernence to a variant in a tuple? */
285
+
286
+ #ifdef _MSC_VER
287
+ TESTCASE(ClassRoundtripRef)
288
+ {
289
+ Module m = define_module("Testing");
290
+
291
+ Object instance = m.module_eval("MyClass1.new");
292
+ Object instance2 = m.call("roundtrip_variant_class_ref", instance);
293
+ String hello = instance2.call("say_hello");
294
+ ASSERT_EQUAL("Hi from MyClass1", detail::From_Ruby<std::string>().convert(hello));
295
+
296
+ instance = m.module_eval("MyClass2.new");
297
+ instance2 = m.call("roundtrip_variant_class_ref", instance);
298
+ hello = instance2.call("say_hello");
299
+ ASSERT_EQUAL("Hi from MyClass2", detail::From_Ruby<std::string>().convert(hello));
300
+ }
301
+ #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
+ }
data/test/test_Struct.cpp CHANGED
@@ -159,7 +159,7 @@ TESTCASE(instance_bracket_index)
159
159
  ASSERT_EQUAL(detail::to_ruby(3), p[2].value());
160
160
  }
161
161
 
162
- /*TESTCASE(instance_swap)
162
+ TESTCASE(instance_swap)
163
163
  {
164
164
  Struct s(define_3d_point());
165
165
 
@@ -171,7 +171,7 @@ TESTCASE(instance_bracket_index)
171
171
  Array args2(a2);
172
172
  Struct::Instance p2(s, args2);
173
173
 
174
- p1.swap(p2);
174
+ std::swap(p1, p2);
175
175
 
176
176
  ASSERT_EQUAL(detail::to_ruby(4), rb_struct_getmember(p1, rb_intern("x")));
177
177
  ASSERT_EQUAL(detail::to_ruby(5), rb_struct_getmember(p1, rb_intern("y")));
@@ -180,7 +180,7 @@ TESTCASE(instance_bracket_index)
180
180
  ASSERT_EQUAL(detail::to_ruby(1), rb_struct_getmember(p2, rb_intern("x")));
181
181
  ASSERT_EQUAL(detail::to_ruby(2), rb_struct_getmember(p2, rb_intern("y")));
182
182
  ASSERT_EQUAL(detail::to_ruby(3), rb_struct_getmember(p2, rb_intern("z")));
183
- }*/
183
+ }
184
184
 
185
185
  /**
186
186
  * Issue 59 - Copy constructor compilation problem.
@@ -322,6 +322,12 @@ TESTCASE(char_const_ptr_to_ruby)
322
322
  {
323
323
  ASSERT(rb_equal(String("").value(), detail::to_ruby((char const *)"")));
324
324
  ASSERT(rb_equal(String("foo").value(), detail::to_ruby((char const *)"foo")));
325
+ ASSERT(rb_equal(String("foo").value(), detail::to_ruby("foo")));
326
+ }
327
+
328
+ TESTCASE(char_const_array_to_ruby_symbol)
329
+ {
330
+ ASSERT(rb_equal(Symbol("foo").value(), detail::to_ruby(":foo")));
325
331
  }
326
332
 
327
333
  TESTCASE(char_const_ptr_from_ruby)