rice 4.0.4 → 4.1.0

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