rice 4.8.0 → 4.9.1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +25 -1
- data/CMakePresets.json +77 -50
- data/FindRuby.cmake +1 -1
- data/bin/rice-doc.rb +2 -0
- data/include/rice/api.hpp +14 -1
- data/include/rice/rice.hpp +351 -132
- data/include/rice/stl.hpp +319 -256
- data/lib/rice/doc/config.rb +57 -57
- data/lib/rice/doc/cpp_reference.rb +158 -158
- data/lib/rice/doc/doxygen.rb +289 -289
- data/lib/rice/doc/mkdocs.rb +332 -332
- data/lib/rice/doc/rice.rb +48 -47
- data/lib/rice/doc/ruby.rb +26 -26
- data/lib/rice/native.rb +15 -15
- data/lib/rice/native_registry.rb +12 -17
- data/lib/rice/parameter.rb +5 -5
- data/lib/rice/rbs.rb +72 -72
- data/lib/rice/version.rb +1 -1
- data/lib/rubygems/builder.rb +9 -9
- data/lib/rubygems_plugin.rb +8 -8
- data/rice/Data_Type.ipp +12 -7
- data/rice/cpp_api/Class.hpp +5 -0
- data/rice/cpp_api/Class.ipp +5 -0
- data/rice/cpp_api/Object.hpp +6 -0
- data/rice/cpp_api/Object.ipp +5 -0
- data/rice/detail/Forwards.hpp +18 -0
- data/rice/detail/Forwards.ipp +60 -0
- data/rice/detail/Native.ipp +2 -4
- data/rice/detail/NativeAttributeGet.ipp +1 -1
- data/rice/detail/NativeAttributeSet.hpp +5 -3
- data/rice/detail/NativeAttributeSet.ipp +41 -33
- data/rice/detail/NativeMethod.ipp +25 -22
- data/rice/detail/NativeRegistry.hpp +4 -2
- data/rice/detail/NativeRegistry.ipp +42 -9
- data/rice/detail/Parameter.ipp +3 -4
- data/rice/detail/Type.ipp +4 -0
- data/rice/detail/Wrapper.hpp +17 -12
- data/rice/detail/Wrapper.ipp +95 -36
- data/rice/rice.hpp +3 -0
- data/rice/rice_api/NativeRegistry.ipp +14 -1
- data/rice/stl/exception.ipp +1 -1
- data/rice/stl/filesystem.ipp +1 -1
- data/rice/stl/map.ipp +13 -11
- data/rice/stl/multimap.ipp +13 -11
- data/rice/stl/pair.ipp +14 -8
- data/rice/stl/set.ipp +16 -16
- data/rice/stl/shared_ptr.hpp +16 -0
- data/rice/stl/shared_ptr.ipp +74 -37
- data/rice/stl/type_index.ipp +1 -1
- data/rice/stl/unique_ptr.hpp +9 -3
- data/rice/stl/unique_ptr.ipp +80 -124
- data/rice/stl/unordered_map.ipp +14 -12
- data/rice/stl/vector.ipp +67 -31
- data/test/test_Attribute.cpp +72 -0
- data/test/test_Callback.cpp +3 -0
- data/test/test_Inheritance.cpp +14 -14
- data/test/test_Keep_Alive_No_Wrapper.cpp +6 -2
- data/test/test_Stl_Map.cpp +46 -0
- data/test/test_Stl_Multimap.cpp +46 -0
- data/test/test_Stl_Set.cpp +34 -0
- data/test/test_Stl_SharedPtr.cpp +160 -45
- data/test/test_Stl_UniquePtr.cpp +48 -3
- data/test/test_Stl_Unordered_Map.cpp +46 -0
- data/test/test_Stl_Variant.cpp +10 -14
- data/test/test_Stl_Vector.cpp +140 -13
- data/test/test_Tracking.cpp +3 -0
- metadata +3 -1
data/rice/stl/vector.ipp
CHANGED
|
@@ -58,13 +58,13 @@ namespace Rice
|
|
|
58
58
|
|
|
59
59
|
if constexpr (std::is_copy_constructible_v<Value_T>)
|
|
60
60
|
{
|
|
61
|
-
klass_.define_constructor(Constructor<T, const T&>())
|
|
62
|
-
.define_constructor(Constructor<T, Size_T, const Parameter_T>());
|
|
61
|
+
klass_.define_constructor(Constructor<T, const T&>(), Arg("other"))
|
|
62
|
+
.define_constructor(Constructor<T, Size_T, const Parameter_T>(), Arg("count"), Arg("value"));
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
if constexpr (std::is_default_constructible_v<Value_T>)
|
|
66
66
|
{
|
|
67
|
-
klass_.define_constructor(Constructor<T, Size_T>());
|
|
67
|
+
klass_.define_constructor(Constructor<T, Size_T>(), Arg("count"));
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
// Allow creation of a vector from a Ruby Array
|
|
@@ -72,18 +72,20 @@ namespace Rice
|
|
|
72
72
|
{
|
|
73
73
|
// Create a new vector from the array
|
|
74
74
|
T* data = new T();
|
|
75
|
-
data->reserve(array.size());
|
|
76
75
|
|
|
76
|
+
// Wrap the vector
|
|
77
|
+
detail::Wrapper<T*>* wrapper = detail::wrapConstructed<T>(self, Data_Type<T>::ruby_data_type(), data);
|
|
78
|
+
|
|
79
|
+
// Now populate the vector
|
|
77
80
|
detail::From_Ruby<Value_T> fromRuby;
|
|
81
|
+
data->reserve(array.size());
|
|
78
82
|
|
|
79
83
|
for (long i = 0; i < array.size(); i++)
|
|
80
84
|
{
|
|
81
85
|
VALUE element = detail::protect(rb_ary_entry, array, i);
|
|
82
86
|
data->push_back(fromRuby.convert(element));
|
|
87
|
+
wrapper->addKeepAlive(element);
|
|
83
88
|
}
|
|
84
|
-
|
|
85
|
-
// Wrap the vector
|
|
86
|
-
detail::wrapConstructed<T>(self, Data_Type<T>::ruby_data_type(), data);
|
|
87
89
|
});
|
|
88
90
|
}
|
|
89
91
|
|
|
@@ -91,18 +93,18 @@ namespace Rice
|
|
|
91
93
|
{
|
|
92
94
|
if constexpr (std::is_default_constructible_v<Value_T> && std::is_same_v<Value_T, bool>)
|
|
93
95
|
{
|
|
94
|
-
klass_.define_method("resize", static_cast<void (T::*)(const size_t, bool)>(&T::resize));
|
|
96
|
+
klass_.define_method("resize", static_cast<void (T::*)(const size_t, bool)>(&T::resize), Arg("count"), Arg("value"));
|
|
95
97
|
}
|
|
96
98
|
else if constexpr (std::is_default_constructible_v<Value_T>)
|
|
97
99
|
{
|
|
98
|
-
klass_.define_method("resize", static_cast<void (T::*)(const size_t)>(&T::resize));
|
|
100
|
+
klass_.define_method("resize", static_cast<void (T::*)(const size_t)>(&T::resize), Arg("count"));
|
|
99
101
|
}
|
|
100
102
|
else
|
|
101
103
|
{
|
|
102
104
|
klass_.define_method("resize", [](const T&, Size_T)
|
|
103
105
|
{
|
|
104
106
|
// Do nothing
|
|
105
|
-
});
|
|
107
|
+
}, Arg("count"));
|
|
106
108
|
}
|
|
107
109
|
}
|
|
108
110
|
|
|
@@ -111,13 +113,11 @@ namespace Rice
|
|
|
111
113
|
klass_.define_method("empty?", &T::empty)
|
|
112
114
|
.define_method("capacity", &T::capacity)
|
|
113
115
|
.define_method("max_size", &T::max_size)
|
|
114
|
-
.define_method("reserve", &T::reserve)
|
|
116
|
+
.define_method("reserve", &T::reserve, Arg("new_cap"))
|
|
115
117
|
.define_method("size", &T::size);
|
|
116
|
-
|
|
118
|
+
|
|
117
119
|
rb_define_alias(klass_, "count", "size");
|
|
118
120
|
rb_define_alias(klass_, "length", "size");
|
|
119
|
-
//detail::protect(rb_define_alias, klass_, "count", "size");
|
|
120
|
-
//detail::protect(rb_define_alias, klass_, "length", "size");
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
void define_access_methods()
|
|
@@ -158,7 +158,7 @@ namespace Rice
|
|
|
158
158
|
{
|
|
159
159
|
return vector[index];
|
|
160
160
|
}
|
|
161
|
-
})
|
|
161
|
+
}, Arg("pos"))
|
|
162
162
|
.template define_method<Value_T*(T::*)()>("data", &T::data, ReturnBuffer());
|
|
163
163
|
}
|
|
164
164
|
else
|
|
@@ -197,7 +197,7 @@ namespace Rice
|
|
|
197
197
|
{
|
|
198
198
|
return vector[index];
|
|
199
199
|
}
|
|
200
|
-
});
|
|
200
|
+
}, Arg("pos"));
|
|
201
201
|
}
|
|
202
202
|
|
|
203
203
|
klass_.define_method("[]", [this](T& vector, Difference_T start, Difference_T length) -> VALUE
|
|
@@ -230,7 +230,7 @@ namespace Rice
|
|
|
230
230
|
|
|
231
231
|
return result;
|
|
232
232
|
}
|
|
233
|
-
}, Return().setValue());
|
|
233
|
+
}, Arg("start"), Arg("length"), Return().setValue());
|
|
234
234
|
|
|
235
235
|
rb_define_alias(klass_, "at", "[]");
|
|
236
236
|
}
|
|
@@ -243,7 +243,7 @@ namespace Rice
|
|
|
243
243
|
klass_.define_method("==", [](T& vector, T& other)->bool
|
|
244
244
|
{
|
|
245
245
|
return vector == other;
|
|
246
|
-
})
|
|
246
|
+
}, Arg("other"))
|
|
247
247
|
.define_method("delete", [](T& vector, Parameter_T element) -> std::optional<Value_T>
|
|
248
248
|
{
|
|
249
249
|
auto iter = std::find(vector.begin(), vector.end(), element);
|
|
@@ -261,11 +261,11 @@ namespace Rice
|
|
|
261
261
|
{
|
|
262
262
|
return std::nullopt;
|
|
263
263
|
}
|
|
264
|
-
})
|
|
264
|
+
}, Arg("value"))
|
|
265
265
|
.define_method("include?", [](T& vector, Parameter_T element)
|
|
266
266
|
{
|
|
267
267
|
return std::find(vector.begin(), vector.end(), element) != vector.end();
|
|
268
|
-
})
|
|
268
|
+
}, Arg("value"))
|
|
269
269
|
.define_method("index", [](T& vector, Parameter_T element) -> std::optional<Difference_T>
|
|
270
270
|
{
|
|
271
271
|
auto iter = std::find(vector.begin(), vector.end(), element);
|
|
@@ -277,7 +277,7 @@ namespace Rice
|
|
|
277
277
|
{
|
|
278
278
|
return iter - vector.begin();
|
|
279
279
|
}
|
|
280
|
-
});
|
|
280
|
+
}, Arg("value"));
|
|
281
281
|
rb_define_alias(klass_, "eql?", "==");
|
|
282
282
|
}
|
|
283
283
|
else
|
|
@@ -285,15 +285,15 @@ namespace Rice
|
|
|
285
285
|
klass_.define_method("delete", [](T&, Parameter_T) -> std::optional<Value_T>
|
|
286
286
|
{
|
|
287
287
|
return std::nullopt;
|
|
288
|
-
})
|
|
288
|
+
}, Arg("value"))
|
|
289
289
|
.define_method("include?", [](const T&, Parameter_T)
|
|
290
290
|
{
|
|
291
291
|
return false;
|
|
292
|
-
})
|
|
292
|
+
}, Arg("value"))
|
|
293
293
|
.define_method("index", [](const T&, Parameter_T) -> std::optional<Difference_T>
|
|
294
294
|
{
|
|
295
295
|
return std::nullopt;
|
|
296
|
-
});
|
|
296
|
+
}, Arg("value"));
|
|
297
297
|
}
|
|
298
298
|
}
|
|
299
299
|
|
|
@@ -315,7 +315,7 @@ namespace Rice
|
|
|
315
315
|
vector.erase(iter);
|
|
316
316
|
return std::nullopt;
|
|
317
317
|
}
|
|
318
|
-
})
|
|
318
|
+
}, Arg("pos"))
|
|
319
319
|
.define_method("insert", [this](T& vector, Difference_T index, Parameter_T element) -> T&
|
|
320
320
|
{
|
|
321
321
|
size_t normalized = normalizeIndex(vector.size(), index, true);
|
|
@@ -329,7 +329,7 @@ namespace Rice
|
|
|
329
329
|
auto iter = vector.begin() + normalized;
|
|
330
330
|
vector.insert(iter, std::move(element));
|
|
331
331
|
return vector;
|
|
332
|
-
})
|
|
332
|
+
}, Arg("pos"), Arg("value").keepAlive())
|
|
333
333
|
.define_method("pop", [](T& vector) -> std::optional<Value_T>
|
|
334
334
|
{
|
|
335
335
|
if constexpr (!std::is_copy_assignable_v<Value_T>)
|
|
@@ -352,13 +352,13 @@ namespace Rice
|
|
|
352
352
|
{
|
|
353
353
|
vector.push_back(std::move(element));
|
|
354
354
|
return vector;
|
|
355
|
-
})
|
|
355
|
+
}, Arg("value").keepAlive())
|
|
356
356
|
.define_method("shrink_to_fit", &T::shrink_to_fit)
|
|
357
357
|
.define_method("[]=", [this](T& vector, Difference_T index, Parameter_T element) -> void
|
|
358
358
|
{
|
|
359
359
|
index = normalizeIndex(vector.size(), index, true);
|
|
360
360
|
vector[index] = std::move(element);
|
|
361
|
-
});
|
|
361
|
+
}, Arg("pos"), Arg("value").keepAlive());
|
|
362
362
|
|
|
363
363
|
rb_define_alias(klass_, "push_back", "push");
|
|
364
364
|
rb_define_alias(klass_, "<<", "push");
|
|
@@ -492,7 +492,19 @@ namespace Rice
|
|
|
492
492
|
case RUBY_T_ARRAY:
|
|
493
493
|
if constexpr (std::is_default_constructible_v<T>)
|
|
494
494
|
{
|
|
495
|
-
|
|
495
|
+
// For proper overload resolution when a function has multiple vector type
|
|
496
|
+
// overloads (e.g., vector<A>& and vector<B>&), we must check if the array
|
|
497
|
+
// elements can actually be converted to T. Otherwise all vector overloads
|
|
498
|
+
// score equally and the wrong one may be selected.
|
|
499
|
+
long size = RARRAY_LEN(value);
|
|
500
|
+
if (size == 0)
|
|
501
|
+
{
|
|
502
|
+
return Convertible::Exact;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
From_Ruby<remove_cv_recursive_t<T>> fromRuby;
|
|
506
|
+
VALUE first = rb_ary_entry(value, 0);
|
|
507
|
+
return fromRuby.is_convertible(first);
|
|
496
508
|
}
|
|
497
509
|
default:
|
|
498
510
|
return Convertible::None;
|
|
@@ -548,7 +560,19 @@ namespace Rice
|
|
|
548
560
|
case RUBY_T_ARRAY:
|
|
549
561
|
if constexpr (std::is_default_constructible_v<T>)
|
|
550
562
|
{
|
|
551
|
-
|
|
563
|
+
// For proper overload resolution when a function has multiple vector type
|
|
564
|
+
// overloads (e.g., vector<A>& and vector<B>&), we must check if the array
|
|
565
|
+
// elements can actually be converted to T. Otherwise all vector overloads
|
|
566
|
+
// score equally and the wrong one may be selected.
|
|
567
|
+
long size = RARRAY_LEN(value);
|
|
568
|
+
if (size == 0)
|
|
569
|
+
{
|
|
570
|
+
return Convertible::Exact;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
From_Ruby<remove_cv_recursive_t<T>> fromRuby;
|
|
574
|
+
VALUE first = rb_ary_entry(value, 0);
|
|
575
|
+
return fromRuby.is_convertible(first);
|
|
552
576
|
}
|
|
553
577
|
default:
|
|
554
578
|
return Convertible::None;
|
|
@@ -609,7 +633,19 @@ namespace Rice
|
|
|
609
633
|
case RUBY_T_ARRAY:
|
|
610
634
|
if constexpr (std::is_default_constructible_v<T>)
|
|
611
635
|
{
|
|
612
|
-
|
|
636
|
+
// For proper overload resolution when a function has multiple vector type
|
|
637
|
+
// overloads (e.g., vector<A>& and vector<B>&), we must check if the array
|
|
638
|
+
// elements can actually be converted to T. Otherwise all vector overloads
|
|
639
|
+
// score equally and the wrong one may be selected.
|
|
640
|
+
long size = RARRAY_LEN(value);
|
|
641
|
+
if (size == 0)
|
|
642
|
+
{
|
|
643
|
+
return Convertible::Exact;
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
From_Ruby<remove_cv_recursive_t<T>> fromRuby;
|
|
647
|
+
VALUE first = rb_ary_entry(value, 0);
|
|
648
|
+
return fromRuby.is_convertible(first);
|
|
613
649
|
}
|
|
614
650
|
default:
|
|
615
651
|
return Convertible::None;
|
data/test/test_Attribute.cpp
CHANGED
|
@@ -22,6 +22,21 @@ TEARDOWN(Attribute)
|
|
|
22
22
|
|
|
23
23
|
namespace
|
|
24
24
|
{
|
|
25
|
+
class MyClass2
|
|
26
|
+
{
|
|
27
|
+
public:
|
|
28
|
+
MyClass2(int value) : value(value)
|
|
29
|
+
{
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
~MyClass2()
|
|
33
|
+
{
|
|
34
|
+
value = -1;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
int value = 0;
|
|
38
|
+
};
|
|
39
|
+
|
|
25
40
|
class SomeClass
|
|
26
41
|
{
|
|
27
42
|
};
|
|
@@ -70,6 +85,7 @@ namespace
|
|
|
70
85
|
char buf[2] = { '0', '1' };
|
|
71
86
|
OldEnum oldEnum = OldValue1;
|
|
72
87
|
NewEnum newEnum = NewEnum::NewValue1;
|
|
88
|
+
MyClass2* myClass2 = nullptr;
|
|
73
89
|
|
|
74
90
|
std::string inspect()
|
|
75
91
|
{
|
|
@@ -496,4 +512,60 @@ TESTCASE(CounterBufferAttribute)
|
|
|
496
512
|
struct.counters_buffer.class)";
|
|
497
513
|
Class klass = (Class)m.module_eval(code);
|
|
498
514
|
ASSERT_EQUAL("Rice::Pointer≺AnonymousNamespace꞉꞉Counter≻", klass.name().c_str());
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
TESTCASE(TakeOwnership)
|
|
518
|
+
{
|
|
519
|
+
Module m = define_module("Testing");
|
|
520
|
+
|
|
521
|
+
define_class<MyClass2>("MyClass2")
|
|
522
|
+
.define_constructor(Constructor<MyClass2, int>());
|
|
523
|
+
|
|
524
|
+
define_class<DataStruct>("DataStruct")
|
|
525
|
+
.define_constructor(Constructor<DataStruct>())
|
|
526
|
+
.define_attr("my_class2", &DataStruct::myClass2, Rice::AttrAccess::ReadWrite, Arg("value").takeOwnership());
|
|
527
|
+
|
|
528
|
+
// Create DataStruct, create MyClass2, assign it, nil it, GC, then verify MyClass2 is still alive
|
|
529
|
+
std::string code = R"(
|
|
530
|
+
data_struct = DataStruct.new
|
|
531
|
+
my_class2 = MyClass2.new(42)
|
|
532
|
+
data_struct.my_class2 = my_class2
|
|
533
|
+
my_class2 = nil
|
|
534
|
+
GC.start
|
|
535
|
+
data_struct
|
|
536
|
+
)";
|
|
537
|
+
|
|
538
|
+
Data_Object<DataStruct> dataStruct = m.module_eval(code);
|
|
539
|
+
|
|
540
|
+
// This should work because ownership was transferred - MyClass2 is now owned by C++
|
|
541
|
+
ASSERT_NOT_EQUAL(nullptr, dataStruct->myClass2);
|
|
542
|
+
ASSERT_EQUAL(42, dataStruct->myClass2->value);
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
TESTCASE(KeepAlive)
|
|
546
|
+
{
|
|
547
|
+
Module m = define_module("Testing");
|
|
548
|
+
|
|
549
|
+
define_class<MyClass2>("MyClass2")
|
|
550
|
+
.define_constructor(Constructor<MyClass2, int>());
|
|
551
|
+
|
|
552
|
+
define_class<DataStruct>("DataStruct")
|
|
553
|
+
.define_constructor(Constructor<DataStruct>())
|
|
554
|
+
.define_attr("my_class2", &DataStruct::myClass2, Rice::AttrAccess::ReadWrite, Arg("value").keepAlive());
|
|
555
|
+
|
|
556
|
+
// Create DataStruct, create MyClass2, assign it, nil it, GC, then verify MyClass2 is still alive
|
|
557
|
+
std::string code = R"(
|
|
558
|
+
data_struct = DataStruct.new
|
|
559
|
+
my_class2 = MyClass2.new(43)
|
|
560
|
+
data_struct.my_class2 = my_class2
|
|
561
|
+
my_class2 = nil
|
|
562
|
+
GC.start
|
|
563
|
+
data_struct
|
|
564
|
+
)";
|
|
565
|
+
|
|
566
|
+
Data_Object<DataStruct> dataStruct = m.module_eval(code);
|
|
567
|
+
|
|
568
|
+
// This should work because keepAlive prevents MyClass2 from being GC'd
|
|
569
|
+
ASSERT_NOT_EQUAL(nullptr, dataStruct->myClass2);
|
|
570
|
+
ASSERT_EQUAL(43, dataStruct->myClass2->value);
|
|
499
571
|
}
|
data/test/test_Callback.cpp
CHANGED
|
@@ -55,7 +55,10 @@ TESTCASE(LambdaCallBack)
|
|
|
55
55
|
ASSERT((globalCallback != nullptr));
|
|
56
56
|
|
|
57
57
|
int ref = 4;
|
|
58
|
+
#pragma GCC diagnostic push
|
|
59
|
+
#pragma GCC diagnostic ignored "-Wwrite-strings"
|
|
58
60
|
char* result = triggerCallback(1, 2, true, "hello", ref);
|
|
61
|
+
#pragma GCC diagnostic pop
|
|
59
62
|
ASSERT_EQUAL("1 - 2.0 - true - hello - 4", result);
|
|
60
63
|
}
|
|
61
64
|
|
data/test/test_Inheritance.cpp
CHANGED
|
@@ -128,12 +128,12 @@ TESTCASE(base_pointer_method_call)
|
|
|
128
128
|
|
|
129
129
|
Module m = define_module("Testing");
|
|
130
130
|
|
|
131
|
-
Object message = m.module_eval(R"
|
|
132
|
-
|
|
131
|
+
Object message = m.module_eval(R"(notification = EmailNotification.new
|
|
132
|
+
notification.message)");
|
|
133
133
|
ASSERT_EQUAL("Email", detail::From_Ruby<std::string>().convert(message));
|
|
134
134
|
|
|
135
|
-
message = m.module_eval(R"
|
|
136
|
-
|
|
135
|
+
message = m.module_eval(R"(notification = PushNotification.new
|
|
136
|
+
notification.message)");
|
|
137
137
|
ASSERT_EQUAL("Push", detail::From_Ruby<std::string>().convert(message));
|
|
138
138
|
}
|
|
139
139
|
|
|
@@ -151,12 +151,12 @@ TESTCASE(base_pointer_function_argument)
|
|
|
151
151
|
define_global_function("process_notification", &processNotification);
|
|
152
152
|
|
|
153
153
|
Module m = define_module("Testing");
|
|
154
|
-
Object message = m.module_eval(R"
|
|
155
|
-
|
|
154
|
+
Object message = m.module_eval(R"(notification = EmailNotification.new
|
|
155
|
+
process_notification(notification))");
|
|
156
156
|
ASSERT_EQUAL("Email", detail::From_Ruby<std::string>().convert(message));
|
|
157
157
|
|
|
158
|
-
message = m.module_eval(R"
|
|
159
|
-
|
|
158
|
+
message = m.module_eval(R"(notification = PushNotification.new
|
|
159
|
+
process_notification(notification))");
|
|
160
160
|
ASSERT_EQUAL("Push", detail::From_Ruby<std::string>().convert(message));
|
|
161
161
|
}
|
|
162
162
|
|
|
@@ -175,12 +175,12 @@ TESTCASE(module_base_pointer_method_call)
|
|
|
175
175
|
|
|
176
176
|
Module m = define_module("Testing");
|
|
177
177
|
|
|
178
|
-
Object message = m.module_eval(R"
|
|
179
|
-
|
|
178
|
+
Object message = m.module_eval(R"(notification = Inheritance::EmailNotification.new
|
|
179
|
+
notification.message)");
|
|
180
180
|
ASSERT_EQUAL("Email", detail::From_Ruby<std::string>().convert(message));
|
|
181
181
|
|
|
182
|
-
message = m.module_eval(R"
|
|
183
|
-
|
|
182
|
+
message = m.module_eval(R"(notification = Inheritance::PushNotification.new
|
|
183
|
+
notification.message)");
|
|
184
184
|
ASSERT_EQUAL("Push", detail::From_Ruby<std::string>().convert(message));
|
|
185
185
|
}
|
|
186
186
|
|
|
@@ -219,8 +219,8 @@ TESTCASE(base_pointer_constructor)
|
|
|
219
219
|
|
|
220
220
|
Module m = define_module("Testing");
|
|
221
221
|
|
|
222
|
-
Object result = m.module_eval(R"
|
|
222
|
+
Object result = m.module_eval(R"(notification = PushNotification.new
|
|
223
223
|
processor = Processor.new(notification)
|
|
224
|
-
processor.process)
|
|
224
|
+
processor.process)");
|
|
225
225
|
ASSERT_EQUAL("Push", detail::From_Ruby<std::string>().convert(result));
|
|
226
226
|
}
|
|
@@ -75,11 +75,15 @@ TESTCASE(test_keep_alive_no_wrapper)
|
|
|
75
75
|
Module m = define_module("TestingModule");
|
|
76
76
|
Object zoo = m.module_eval("@zoo = Zoo.new");
|
|
77
77
|
|
|
78
|
+
std::string code = R"(@zoo.get_pets.each do |pet|
|
|
79
|
+
puts pet.get_name
|
|
80
|
+
end)";
|
|
81
|
+
|
|
78
82
|
// get_pets returns an Array (builtin type) so Return().keepAlive()
|
|
79
|
-
//
|
|
83
|
+
// should result in std::runtime_error
|
|
80
84
|
ASSERT_EXCEPTION_CHECK(
|
|
81
85
|
Exception,
|
|
82
|
-
m.module_eval(
|
|
86
|
+
m.module_eval(code),
|
|
83
87
|
ASSERT_EQUAL("wrong argument type Array (expected wrapped C++ object)",
|
|
84
88
|
ex.what())
|
|
85
89
|
);
|
data/test/test_Stl_Map.cpp
CHANGED
|
@@ -706,3 +706,49 @@ TESTCASE(MapToHash)
|
|
|
706
706
|
ASSERT_EQUAL("2", detail::From_Ruby<std::string>().convert(hash["Two"].value()));
|
|
707
707
|
ASSERT_EQUAL("3", detail::From_Ruby<std::string>().convert(hash["Three"].value()));
|
|
708
708
|
}
|
|
709
|
+
|
|
710
|
+
namespace
|
|
711
|
+
{
|
|
712
|
+
class MyClass2
|
|
713
|
+
{
|
|
714
|
+
public:
|
|
715
|
+
MyClass2(std::string name): name(name)
|
|
716
|
+
{
|
|
717
|
+
}
|
|
718
|
+
std::string name;
|
|
719
|
+
};
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
TESTCASE(KeepAlive)
|
|
723
|
+
{
|
|
724
|
+
Class c = define_class<MyClass2>("MyClass2").
|
|
725
|
+
define_constructor(Constructor<MyClass2, std::string>()).
|
|
726
|
+
define_attr("name", &MyClass2::name, AttrAccess::Read);
|
|
727
|
+
|
|
728
|
+
define_map<std::string, MyClass2*>("MyClass2PointerMap");
|
|
729
|
+
|
|
730
|
+
Module m = define_module("Testing");
|
|
731
|
+
|
|
732
|
+
std::string code = R"(
|
|
733
|
+
map = Std::MyClass2PointerMap.new
|
|
734
|
+
|
|
735
|
+
# Test []=
|
|
736
|
+
map["one"] = MyClass2.new("instance1")
|
|
737
|
+
map["two"] = MyClass2.new("instance2")
|
|
738
|
+
map["three"] = MyClass2.new("instance3")
|
|
739
|
+
|
|
740
|
+
GC.start
|
|
741
|
+
|
|
742
|
+
names = []
|
|
743
|
+
map.each do |pair|
|
|
744
|
+
names << pair.second.name
|
|
745
|
+
end
|
|
746
|
+
names.sort
|
|
747
|
+
)";
|
|
748
|
+
|
|
749
|
+
Array result = m.module_eval(code);
|
|
750
|
+
ASSERT_EQUAL(3, result.size());
|
|
751
|
+
ASSERT_EQUAL("instance1", detail::From_Ruby<std::string>().convert(result[0].value()));
|
|
752
|
+
ASSERT_EQUAL("instance2", detail::From_Ruby<std::string>().convert(result[1].value()));
|
|
753
|
+
ASSERT_EQUAL("instance3", detail::From_Ruby<std::string>().convert(result[2].value()));
|
|
754
|
+
}
|
data/test/test_Stl_Multimap.cpp
CHANGED
|
@@ -690,4 +690,50 @@ TESTCASE(HashToMultimapMixedTypes)
|
|
|
690
690
|
m.module_eval(code),
|
|
691
691
|
ASSERT_EQUAL("no implicit conversion of String into Integer", ex.what())
|
|
692
692
|
);
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
namespace
|
|
696
|
+
{
|
|
697
|
+
class MyClass2
|
|
698
|
+
{
|
|
699
|
+
public:
|
|
700
|
+
MyClass2(std::string name): name(name)
|
|
701
|
+
{
|
|
702
|
+
}
|
|
703
|
+
std::string name;
|
|
704
|
+
};
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
TESTCASE(KeepAlive)
|
|
708
|
+
{
|
|
709
|
+
Class c = define_class<MyClass2>("MyClass2").
|
|
710
|
+
define_constructor(Constructor<MyClass2, std::string>()).
|
|
711
|
+
define_attr("name", &MyClass2::name, AttrAccess::Read);
|
|
712
|
+
|
|
713
|
+
define_multimap<std::string, MyClass2*>("MyClass2PointerMultimap");
|
|
714
|
+
|
|
715
|
+
Module m = define_module("Testing");
|
|
716
|
+
|
|
717
|
+
std::string code = R"(
|
|
718
|
+
map = Std::MyClass2PointerMultimap.new
|
|
719
|
+
|
|
720
|
+
# Test insert
|
|
721
|
+
map.insert("one", MyClass2.new("instance1"))
|
|
722
|
+
map.insert("two", MyClass2.new("instance2"))
|
|
723
|
+
map.insert("three", MyClass2.new("instance3"))
|
|
724
|
+
|
|
725
|
+
GC.start
|
|
726
|
+
|
|
727
|
+
names = []
|
|
728
|
+
map.each do |pair|
|
|
729
|
+
names << pair.second.name
|
|
730
|
+
end
|
|
731
|
+
names.sort
|
|
732
|
+
)";
|
|
733
|
+
|
|
734
|
+
Array result = m.module_eval(code);
|
|
735
|
+
ASSERT_EQUAL(3, result.size());
|
|
736
|
+
ASSERT_EQUAL("instance1", detail::From_Ruby<std::string>().convert(result[0].value()));
|
|
737
|
+
ASSERT_EQUAL("instance2", detail::From_Ruby<std::string>().convert(result[1].value()));
|
|
738
|
+
ASSERT_EQUAL("instance3", detail::From_Ruby<std::string>().convert(result[2].value()));
|
|
693
739
|
}
|
data/test/test_Stl_Set.cpp
CHANGED
|
@@ -788,3 +788,37 @@ TESTCASE(Superset)
|
|
|
788
788
|
Object result = m.instance_eval(code);
|
|
789
789
|
ASSERT_EQUAL(Qtrue, result.value());
|
|
790
790
|
}
|
|
791
|
+
|
|
792
|
+
TESTCASE(KeepAlive)
|
|
793
|
+
{
|
|
794
|
+
Class c = define_class<MyClass2>("MyClass2").
|
|
795
|
+
define_constructor(Constructor<MyClass2, std::string>()).
|
|
796
|
+
define_attr("name", &MyClass2::name, AttrAccess::Read);
|
|
797
|
+
|
|
798
|
+
define_set<MyClass2*>("MyClass2PointerSet");
|
|
799
|
+
|
|
800
|
+
Module m = define_module("Testing");
|
|
801
|
+
|
|
802
|
+
std::string code = R"(
|
|
803
|
+
set = Std::MyClass2PointerSet.new
|
|
804
|
+
|
|
805
|
+
# Test insert
|
|
806
|
+
set.insert(MyClass2.new("instance1"))
|
|
807
|
+
set.insert(MyClass2.new("instance2"))
|
|
808
|
+
set.insert(MyClass2.new("instance3"))
|
|
809
|
+
|
|
810
|
+
GC.start
|
|
811
|
+
|
|
812
|
+
names = []
|
|
813
|
+
set.each do |instance|
|
|
814
|
+
names << instance.name
|
|
815
|
+
end
|
|
816
|
+
names.sort
|
|
817
|
+
)";
|
|
818
|
+
|
|
819
|
+
Array result = m.module_eval(code);
|
|
820
|
+
ASSERT_EQUAL(3, result.size());
|
|
821
|
+
ASSERT_EQUAL("instance1", detail::From_Ruby<std::string>().convert(result[0].value()));
|
|
822
|
+
ASSERT_EQUAL("instance2", detail::From_Ruby<std::string>().convert(result[1].value()));
|
|
823
|
+
ASSERT_EQUAL("instance3", detail::From_Ruby<std::string>().convert(result[2].value()));
|
|
824
|
+
}
|