rice 4.7.1 → 4.9.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 (160) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +37 -1
  3. data/CMakeLists.txt +14 -22
  4. data/CMakePresets.json +203 -75
  5. data/FindRuby.cmake +358 -123
  6. data/bin/rice-doc.rb +58 -141
  7. data/include/rice/api.hpp +261 -0
  8. data/include/rice/rice.hpp +2459 -1693
  9. data/include/rice/stl.hpp +450 -546
  10. data/lib/rice/doc/config.rb +70 -0
  11. data/lib/rice/doc/cpp_reference.rb +1 -4
  12. data/lib/rice/doc/mkdocs.rb +58 -20
  13. data/lib/rice/doc/rice.rb +21 -0
  14. data/lib/rice/doc.rb +1 -0
  15. data/lib/rice/make_rice_headers.rb +7 -0
  16. data/lib/rice/native_registry.rb +5 -10
  17. data/lib/rice/rbs.rb +6 -6
  18. data/lib/rice/version.rb +1 -1
  19. data/lib/rubygems_plugin.rb +12 -9
  20. data/rice/Arg.hpp +12 -6
  21. data/rice/Arg.ipp +14 -7
  22. data/rice/Buffer.ipp +44 -40
  23. data/rice/Callback.hpp +1 -1
  24. data/rice/Callback.ipp +2 -7
  25. data/rice/Constructor.hpp +1 -1
  26. data/rice/Constructor.ipp +11 -11
  27. data/rice/Data_Object.ipp +15 -15
  28. data/rice/Data_Type.hpp +9 -10
  29. data/rice/Data_Type.ipp +33 -31
  30. data/rice/Director.hpp +1 -0
  31. data/rice/Enum.ipp +58 -39
  32. data/rice/Exception.hpp +4 -4
  33. data/rice/Exception.ipp +7 -7
  34. data/rice/NoGVL.hpp +13 -0
  35. data/rice/Reference.hpp +56 -0
  36. data/rice/Reference.ipp +96 -0
  37. data/rice/Return.hpp +4 -1
  38. data/rice/Return.ipp +0 -6
  39. data/rice/cpp_api/Array.hpp +41 -4
  40. data/rice/cpp_api/Array.ipp +105 -9
  41. data/rice/cpp_api/Class.hpp +7 -2
  42. data/rice/cpp_api/Class.ipp +9 -4
  43. data/rice/cpp_api/Hash.ipp +7 -4
  44. data/rice/cpp_api/Module.hpp +4 -4
  45. data/rice/cpp_api/Module.ipp +12 -10
  46. data/rice/cpp_api/Object.hpp +10 -4
  47. data/rice/cpp_api/Object.ipp +20 -12
  48. data/rice/cpp_api/String.hpp +2 -2
  49. data/rice/cpp_api/String.ipp +11 -8
  50. data/rice/cpp_api/Symbol.ipp +7 -7
  51. data/rice/cpp_api/shared_methods.hpp +5 -9
  52. data/rice/detail/Forwards.hpp +18 -0
  53. data/rice/detail/Forwards.ipp +60 -0
  54. data/rice/detail/InstanceRegistry.hpp +0 -2
  55. data/rice/detail/Native.hpp +31 -21
  56. data/rice/detail/Native.ipp +282 -130
  57. data/rice/detail/NativeAttributeGet.hpp +5 -7
  58. data/rice/detail/NativeAttributeGet.ipp +26 -26
  59. data/rice/detail/NativeAttributeSet.hpp +2 -4
  60. data/rice/detail/NativeAttributeSet.ipp +20 -16
  61. data/rice/detail/NativeCallback.hpp +77 -0
  62. data/rice/detail/NativeCallback.ipp +280 -0
  63. data/rice/detail/NativeFunction.hpp +11 -21
  64. data/rice/detail/NativeFunction.ipp +58 -119
  65. data/rice/detail/NativeInvoker.hpp +4 -4
  66. data/rice/detail/NativeInvoker.ipp +7 -7
  67. data/rice/detail/NativeIterator.hpp +2 -4
  68. data/rice/detail/NativeIterator.ipp +18 -14
  69. data/rice/detail/NativeMethod.hpp +10 -20
  70. data/rice/detail/NativeMethod.ipp +54 -114
  71. data/rice/detail/NativeProc.hpp +5 -7
  72. data/rice/detail/NativeProc.ipp +39 -28
  73. data/rice/detail/NativeRegistry.hpp +1 -1
  74. data/rice/detail/NativeRegistry.ipp +29 -0
  75. data/rice/detail/Parameter.hpp +15 -8
  76. data/rice/detail/Parameter.ipp +102 -43
  77. data/rice/detail/Proc.ipp +14 -28
  78. data/rice/detail/RubyType.ipp +2 -53
  79. data/rice/detail/Type.hpp +23 -7
  80. data/rice/detail/Type.ipp +77 -93
  81. data/rice/detail/TypeRegistry.ipp +5 -4
  82. data/rice/detail/Wrapper.hpp +13 -12
  83. data/rice/detail/Wrapper.ipp +97 -44
  84. data/rice/detail/from_ruby.hpp +8 -6
  85. data/rice/detail/from_ruby.ipp +306 -173
  86. data/rice/detail/ruby.hpp +23 -0
  87. data/rice/libc/file.hpp +4 -4
  88. data/rice/rice.hpp +9 -8
  89. data/rice/rice_api/Native.ipp +5 -1
  90. data/rice/rice_api/NativeRegistry.ipp +14 -1
  91. data/rice/rice_api/Parameter.ipp +1 -1
  92. data/rice/ruby_mark.hpp +2 -1
  93. data/rice/stl/complex.ipp +12 -8
  94. data/rice/stl/map.ipp +27 -22
  95. data/rice/stl/monostate.ipp +16 -12
  96. data/rice/stl/multimap.hpp +0 -2
  97. data/rice/stl/multimap.ipp +27 -22
  98. data/rice/stl/optional.ipp +27 -11
  99. data/rice/stl/pair.ipp +5 -5
  100. data/rice/stl/reference_wrapper.ipp +5 -4
  101. data/rice/stl/set.ipp +16 -16
  102. data/rice/stl/shared_ptr.hpp +9 -9
  103. data/rice/stl/shared_ptr.ipp +52 -185
  104. data/rice/stl/string.ipp +18 -18
  105. data/rice/stl/string_view.ipp +1 -1
  106. data/rice/stl/tuple.ipp +15 -36
  107. data/rice/stl/unique_ptr.hpp +9 -3
  108. data/rice/stl/unique_ptr.ipp +86 -120
  109. data/rice/stl/unordered_map.ipp +20 -15
  110. data/rice/stl/variant.ipp +37 -21
  111. data/rice/stl/vector.ipp +41 -36
  112. data/rice/traits/function_traits.hpp +19 -19
  113. data/rice/traits/method_traits.hpp +4 -4
  114. data/rice/traits/rice_traits.hpp +162 -39
  115. data/rice.gemspec +1 -3
  116. data/test/test_Array.cpp +261 -3
  117. data/test/test_Attribute.cpp +6 -3
  118. data/test/test_Buffer.cpp +6 -42
  119. data/test/test_Callback.cpp +77 -23
  120. data/test/test_Data_Object.cpp +1 -1
  121. data/test/test_Data_Type.cpp +21 -22
  122. data/test/test_Director.cpp +2 -4
  123. data/test/test_Enum.cpp +34 -5
  124. data/test/test_File.cpp +9 -5
  125. data/test/test_From_Ruby.cpp +4 -3
  126. data/test/test_GVL.cpp +3 -3
  127. data/test/test_Hash.cpp +1 -1
  128. data/test/test_Inheritance.cpp +14 -14
  129. data/test/test_Iterator.cpp +54 -22
  130. data/test/test_Keep_Alive.cpp +1 -1
  131. data/test/test_Keep_Alive_No_Wrapper.cpp +7 -3
  132. data/test/test_Module.cpp +5 -5
  133. data/test/test_Overloads.cpp +345 -48
  134. data/test/test_Proc.cpp +54 -0
  135. data/test/test_Reference.cpp +181 -0
  136. data/test/test_Self.cpp +2 -2
  137. data/test/test_Stl_Set.cpp +6 -6
  138. data/test/test_Stl_SharedPtr.cpp +172 -33
  139. data/test/test_Stl_String_View.cpp +4 -2
  140. data/test/test_Stl_Tuple.cpp +1 -1
  141. data/test/test_Stl_UniquePtr.cpp +48 -3
  142. data/test/test_Stl_Variant.cpp +6 -14
  143. data/test/test_Stl_Vector.cpp +61 -30
  144. data/test/test_String.cpp +4 -2
  145. data/test/test_Struct.cpp +1 -1
  146. data/test/test_Symbol.cpp +1 -1
  147. data/test/test_To_Ruby.cpp +1 -0
  148. data/test/test_Type.cpp +36 -35
  149. data/test/test_global_functions.cpp +1 -1
  150. data/test/unittest.cpp +1 -1
  151. data/test/unittest.hpp +5 -5
  152. metadata +12 -10
  153. data/rice/Function.hpp +0 -17
  154. data/rice/Function.ipp +0 -13
  155. data/rice/detail/MethodInfo.hpp +0 -48
  156. data/rice/detail/MethodInfo.ipp +0 -99
  157. data/rice/detail/NativeCallbackFFI.hpp +0 -55
  158. data/rice/detail/NativeCallbackFFI.ipp +0 -152
  159. data/rice/detail/NativeCallbackSimple.hpp +0 -30
  160. data/rice/detail/NativeCallbackSimple.ipp +0 -29
@@ -0,0 +1,181 @@
1
+ #include "unittest.hpp"
2
+ #include "embed_ruby.hpp"
3
+ #include <rice/rice.hpp>
4
+
5
+ using namespace Rice;
6
+
7
+ TESTSUITE(Reference);
8
+
9
+ SETUP(Reference)
10
+ {
11
+ embed_ruby();
12
+ }
13
+
14
+ TEARDOWN(Reference)
15
+ {
16
+ rb_gc_start();
17
+ }
18
+
19
+ namespace
20
+ {
21
+ void updateIntRef(int& ref)
22
+ {
23
+ ref = 42;
24
+ }
25
+
26
+ int readIntRef(int& ref)
27
+ {
28
+ return ref;
29
+ }
30
+
31
+ double readDoubleRef(double& ref)
32
+ {
33
+ return ref;
34
+ }
35
+
36
+ bool readBoolRef(bool& ref)
37
+ {
38
+ return ref;
39
+ }
40
+
41
+ char readCharRef(char& ref)
42
+ {
43
+ return ref;
44
+ }
45
+
46
+ long readLongRef(long& ref)
47
+ {
48
+ return ref;
49
+ }
50
+
51
+ long long readLongLongRef(long long& ref)
52
+ {
53
+ return ref;
54
+ }
55
+
56
+ unsigned long long readUnsignedLongLongRef(unsigned long long& ref)
57
+ {
58
+ return ref;
59
+ }
60
+ }
61
+
62
+ TESTCASE(pass_fundamental_to_reference)
63
+ {
64
+ Module m = define_module("Testing");
65
+ m.define_module_function("read_int_ref", &readIntRef);
66
+
67
+ std::string code = R"(read_int_ref(7))";
68
+ Object result = m.module_eval(code);
69
+ ASSERT_EQUAL(7, detail::From_Ruby<int>().convert(result));
70
+ }
71
+
72
+ TESTCASE(pass_reference_object)
73
+ {
74
+ Module m = define_module("Testing");
75
+ m.define_module_function("read_int_ref", &readIntRef);
76
+
77
+ std::string code = R"(ref = Rice::Reference≺int≻.new(7)
78
+ read_int_ref(ref))";
79
+
80
+ Object result = m.module_eval(code);
81
+ ASSERT_EQUAL(7, detail::From_Ruby<int>().convert(result));
82
+ }
83
+
84
+ TESTCASE(modify_reference_object)
85
+ {
86
+ Module m = define_module("Testing");
87
+ m.define_module_function("update_int_ref", &updateIntRef);
88
+
89
+ std::string code = R"(ref = Rice::Reference≺int≻.new(7)
90
+ update_int_ref(ref)
91
+ ref.value)";
92
+
93
+ Object result = m.module_eval(code);
94
+ ASSERT_EQUAL(42, detail::From_Ruby<int>().convert(result));
95
+ }
96
+
97
+ TESTCASE(double_reference)
98
+ {
99
+ Module m = define_module("Testing");
100
+ m.define_module_function("read_double_ref", &readDoubleRef);
101
+
102
+ std::string code = R"(read_double_ref(2.5))";
103
+ Object result = m.module_eval(code);
104
+ ASSERT_EQUAL(2.5, detail::From_Ruby<double>().convert(result));
105
+ }
106
+
107
+ TESTCASE(bool_reference)
108
+ {
109
+ Module m = define_module("Testing");
110
+ m.define_module_function("read_bool_ref", &readBoolRef);
111
+
112
+ std::string code = R"(read_bool_ref(true))";
113
+ Object result = m.module_eval(code);
114
+ ASSERT_EQUAL(Qtrue, result.value());
115
+
116
+ code = R"(read_bool_ref(false))";
117
+ result = m.module_eval(code);
118
+ ASSERT_EQUAL(Qfalse, result.value());
119
+ }
120
+
121
+ TESTCASE(reference_preserves_value)
122
+ {
123
+ Module m = define_module("Testing");
124
+ m.define_module_function("read_int_ref", &readIntRef);
125
+
126
+ std::string code = R"(read_int_ref(0))";
127
+ Object result = m.module_eval(code);
128
+ ASSERT_EQUAL(0, detail::From_Ruby<int>().convert(result));
129
+
130
+ code = R"(read_int_ref(-1))";
131
+ result = m.module_eval(code);
132
+ ASSERT_EQUAL(-1, detail::From_Ruby<int>().convert(result));
133
+
134
+ code = R"(read_int_ref(1000000))";
135
+ result = m.module_eval(code);
136
+ ASSERT_EQUAL(1000000, detail::From_Ruby<int>().convert(result));
137
+ }
138
+
139
+ TESTCASE(char_reference)
140
+ {
141
+ Module m = define_module("Testing");
142
+ m.define_module_function("read_char_ref", &readCharRef);
143
+
144
+ std::string code = R"(read_char_ref(65))";
145
+ Object result = m.module_eval(code);
146
+ ASSERT_EQUAL('A', detail::From_Ruby<char>().convert(result));
147
+ }
148
+
149
+ TESTCASE(long_reference)
150
+ {
151
+ Module m = define_module("Testing");
152
+ m.define_module_function("read_long_ref", &readLongRef);
153
+
154
+ std::string code = R"(read_long_ref(123456789))";
155
+ Object result = m.module_eval(code);
156
+ ASSERT_EQUAL(123456789, detail::From_Ruby<long>().convert(result));
157
+ }
158
+
159
+ TESTCASE(long_long_reference)
160
+ {
161
+ Module m = define_module("Testing");
162
+ m.define_module_function("read_long_long_ref", &readLongLongRef);
163
+
164
+ std::string code = R"(read_long_long_ref(9223372036854775807))";
165
+ Object result = m.module_eval(code);
166
+ ASSERT_EQUAL(9223372036854775807LL, detail::From_Ruby<long long>().convert(result));
167
+ }
168
+
169
+ TESTCASE(unsigned_long_long_reference)
170
+ {
171
+ // Special case: VALUE is unsigned long long on Windows x64, so we can't
172
+ // use Reference<unsigned long long>. Instead, the old pattern is used
173
+ // which stores the converted value directly.
174
+ Module m = define_module("Testing");
175
+ m.define_module_function("read_unsigned_long_long_ref", &readUnsignedLongLongRef);
176
+
177
+ std::string code = R"(read_unsigned_long_long_ref(73))";
178
+ Object result = m.module_eval(code);
179
+ ASSERT_EQUAL(73ULL, detail::From_Ruby<unsigned long long>().convert(result));
180
+ }
181
+
data/test/test_Self.cpp CHANGED
@@ -39,12 +39,12 @@ namespace
39
39
  destructorCalls++;
40
40
  }
41
41
 
42
- SelfClass(const SelfClass& other)
42
+ SelfClass(const SelfClass&)
43
43
  {
44
44
  copyConstructorCalls++;
45
45
  }
46
46
 
47
- SelfClass(SelfClass&& other)
47
+ SelfClass(SelfClass&&)
48
48
  {
49
49
  moveConstructorCalls++;
50
50
  }
@@ -349,7 +349,7 @@ TESTCASE(ToArray)
349
349
  set.to_a)";
350
350
 
351
351
  Array array = m.module_eval(code);
352
- ASSERT_EQUAL(3u, array.size());
352
+ ASSERT_EQUAL(3, array.size());
353
353
 
354
354
  ASSERT_EQUAL("abc", detail::From_Ruby<std::string>().convert(array[0].value()));
355
355
  ASSERT_EQUAL("def", detail::From_Ruby<std::string>().convert(array[1].value()));
@@ -507,11 +507,11 @@ namespace
507
507
  static inline std::set<std::string> instance_{ "one", "two", "three" };
508
508
  };
509
509
 
510
- std::ostream& operator<<(std::ostream& stream, const std::set<std::string>& set)
510
+ /* std::ostream& operator<<(std::ostream& stream, const std::set<std::string>& set)
511
511
  {
512
- stream << "Set";
512
+ stream << set;
513
513
  return stream;
514
- }
514
+ }*/
515
515
 
516
516
  void createFactoryClass()
517
517
  {
@@ -645,7 +645,7 @@ TESTCASE(StringPointerSet)
645
645
 
646
646
  Module m(rb_mKernel);
647
647
  Data_Object<std::set<std::string*>> set = m.call("set_of_string_pointers");
648
- ASSERT_EQUAL(1, set->size());
648
+ ASSERT_EQUAL(1u, set->size());
649
649
 
650
650
  std::string expected = "Hello";
651
651
  const std::string* actual = *set->begin();
@@ -682,7 +682,7 @@ TESTCASE(MyClass2PointerSet)
682
682
 
683
683
  Module m(rb_mKernel);
684
684
  Data_Object<std::set<MyClass2*>> result = m.call("set_of_myclass2_pointers");
685
- ASSERT_EQUAL(1, result->size());
685
+ ASSERT_EQUAL(1u, result->size());
686
686
 
687
687
  MyClass2* pMyClass = *result->begin();
688
688
  ASSERT_EQUAL("Hello MyClass2", pMyClass->name);
@@ -29,6 +29,8 @@ namespace
29
29
 
30
30
  public:
31
31
  int flag = 0;
32
+ std::string name = "default";
33
+ int threshold = 0;
32
34
 
33
35
  public:
34
36
  MyClass()
@@ -57,6 +59,17 @@ namespace
57
59
  }
58
60
  };
59
61
 
62
+ class MyClassInherited : public MyClass
63
+ {
64
+ public:
65
+ int extra = 0;
66
+
67
+ void setExtra(int value)
68
+ {
69
+ this->extra = value;
70
+ }
71
+ };
72
+
60
73
  class Factory
61
74
  {
62
75
  public:
@@ -87,6 +100,11 @@ namespace
87
100
  return instance_;
88
101
  }
89
102
 
103
+ std::shared_ptr<MyClassInherited> share_inherited()
104
+ {
105
+ return std::make_shared<MyClassInherited>();
106
+ }
107
+
90
108
  public:
91
109
  static inline std::shared_ptr<MyClass> instance_;
92
110
  };
@@ -138,12 +156,20 @@ SETUP(SharedPtr)
138
156
 
139
157
  define_class<MyClass>("MyClass").
140
158
  define_constructor(Constructor<MyClass>()).
141
- define_method("set_flag", &MyClass::setFlag);
159
+ define_method("set_flag", &MyClass::setFlag).
160
+ define_attr("name", &MyClass::name, Rice::AttrAccess::Read).
161
+ define_attr("threshold", &MyClass::threshold);
162
+
163
+ define_class<MyClassInherited, MyClass>("MyClassInherited").
164
+ define_constructor(Constructor<MyClassInherited>()).
165
+ define_method("set_extra", &MyClassInherited::setExtra).
166
+ define_attr("extra", &MyClassInherited::extra);
142
167
 
143
168
  define_class<Factory>("Factory").
144
169
  define_constructor(Constructor<Factory>()).
145
170
  define_method("share", &Factory::share).
146
- define_method("share_ref", &Factory::share_ref);
171
+ define_method("share_ref", &Factory::share_ref).
172
+ define_method("share_inherited", &Factory::share_inherited);
147
173
 
148
174
  define_class<Sink>("Sink").
149
175
  define_constructor(Constructor<Sink>()).
@@ -173,8 +199,8 @@ TEARDOWN(SharedPtr)
173
199
 
174
200
  TESTCASE(ShareOwnership)
175
201
  {
176
- MyClass::reset();
177
202
  Factory::reset();
203
+ MyClass::reset();
178
204
 
179
205
  Module m = define_module("TestingModule");
180
206
 
@@ -203,8 +229,8 @@ TESTCASE(ShareOwnership)
203
229
 
204
230
  TESTCASE(ShareOwnership2)
205
231
  {
206
- MyClass::reset();
207
232
  Factory::reset();
233
+ MyClass::reset();
208
234
 
209
235
  Module m = define_module("TestingModule");
210
236
 
@@ -215,24 +241,25 @@ TESTCASE(ShareOwnership2)
215
241
  my_class.set_flag(i)
216
242
  end)";
217
243
 
218
- Factory factory;
219
- std::shared_ptr<MyClass> myClass = factory.share();
220
- ASSERT_EQUAL(2, Factory::instance_.use_count());
221
-
222
- // Call some ruby code
223
- Data_Object<Factory> wrapper(factory);
224
- ASSERT_EQUAL(2, Factory::instance_.use_count());
225
- wrapper.instance_eval("self.share_ref.set_flag(1)");
244
+ ASSERT_EQUAL(0, Factory::instance_.use_count());
245
+ m.module_eval(code);
226
246
 
227
- ASSERT_EQUAL(3, Factory::instance_.use_count());
247
+ ASSERT_EQUAL(11, Factory::instance_.use_count());
228
248
  rb_gc_start();
229
- ASSERT_EQUAL(2, Factory::instance_.use_count());
249
+ ASSERT_EQUAL(1, Factory::instance_.use_count());
250
+
251
+ ASSERT_EQUAL(1, MyClass::constructorCalls);
252
+ ASSERT_EQUAL(0, MyClass::copyConstructorCalls);
253
+ ASSERT_EQUAL(0, MyClass::moveConstructorCalls);
254
+ ASSERT_EQUAL(0, MyClass::destructorCalls);
255
+ ASSERT_EQUAL(9, Factory::instance_->flag);
256
+
230
257
  }
231
258
 
232
259
  TESTCASE(PtrParameter)
233
260
  {
234
- MyClass::reset();
235
261
  Factory::reset();
262
+ MyClass::reset();
236
263
 
237
264
  Module m = define_module("TestingModule");
238
265
 
@@ -247,8 +274,8 @@ TESTCASE(PtrParameter)
247
274
 
248
275
  TESTCASE(RefParameter)
249
276
  {
250
- MyClass::reset();
251
277
  Factory::reset();
278
+ MyClass::reset();
252
279
 
253
280
  Module m = define_module("TestingModule");
254
281
 
@@ -263,8 +290,8 @@ TESTCASE(RefParameter)
263
290
 
264
291
  TESTCASE(DefaultParameter)
265
292
  {
266
- MyClass::reset();
267
293
  Factory::reset();
294
+ MyClass::reset();
268
295
 
269
296
  Module m = define_module("TestingModule");
270
297
 
@@ -280,8 +307,8 @@ TESTCASE(DefaultParameter)
280
307
 
281
308
  TESTCASE(RefDefaultParameter)
282
309
  {
283
- MyClass::reset();
284
310
  Factory::reset();
311
+ MyClass::reset();
285
312
 
286
313
  Module m = define_module("TestingModule");
287
314
 
@@ -299,13 +326,13 @@ TESTCASE(RefDefaultParameter)
299
326
  ASSERT_EQUAL(1, MyClass::constructorCalls);
300
327
  ASSERT_EQUAL(0, MyClass::copyConstructorCalls);
301
328
  ASSERT_EQUAL(0, MyClass::moveConstructorCalls);
302
- ASSERT_EQUAL(1, MyClass::destructorCalls);
329
+ ASSERT_EQUAL(0, MyClass::destructorCalls);
303
330
  }
304
331
 
305
332
  TESTCASE(RoundTrip)
306
333
  {
307
- MyClass::reset();
308
334
  Factory::reset();
335
+ MyClass::reset();
309
336
 
310
337
  Module m = define_module("TestingModule");
311
338
 
@@ -322,13 +349,13 @@ TESTCASE(RoundTrip)
322
349
  ASSERT_EQUAL(1, MyClass::constructorCalls);
323
350
  ASSERT_EQUAL(0, MyClass::copyConstructorCalls);
324
351
  ASSERT_EQUAL(0, MyClass::moveConstructorCalls);
325
- ASSERT_EQUAL(1, MyClass::destructorCalls);
352
+ ASSERT_EQUAL(0, MyClass::destructorCalls);
326
353
  }
327
354
 
328
355
  TESTCASE(Update)
329
356
  {
330
- MyClass::reset();
331
357
  Factory::reset();
358
+ MyClass::reset();
332
359
 
333
360
  Module m = define_module("TestingModule");
334
361
 
@@ -349,8 +376,10 @@ TESTCASE(Update)
349
376
 
350
377
  TESTCASE(Klass)
351
378
  {
379
+ define_shared_ptr<MyClass>();
352
380
  detail::TypeMapper<std::shared_ptr<MyClass>> typeMapper;
353
- Object expected = Object(rb_cObject).const_get("MyClass");
381
+ Module aModule("Std");
382
+ Object expected = aModule.const_get("SharedPtr≺AnonymousNamespace꞉꞉MyClass≻");
354
383
  VALUE actual = typeMapper.rubyKlass();
355
384
  ASSERT_EQUAL(expected.value(), actual);
356
385
  }
@@ -368,8 +397,8 @@ TESTCASE(KlassSharedPtr)
368
397
 
369
398
  TESTCASE(Void)
370
399
  {
371
- MyClass::reset();
372
400
  Factory::reset();
401
+ MyClass::reset();
373
402
 
374
403
  Module m = define_module("TestingModule");
375
404
 
@@ -400,11 +429,23 @@ namespace
400
429
  return shared;
401
430
  }
402
431
 
432
+ const std::shared_ptr<int> createConstPointer(int value)
433
+ {
434
+ int* sharedInt = new int(value);
435
+ const std::shared_ptr<int> shared(sharedInt);
436
+ return shared;
437
+ }
438
+
403
439
  int getPointerValue(std::shared_ptr<int> ptr)
404
440
  {
405
441
  return *ptr;
406
442
  }
407
443
 
444
+ int getConstPointerValue(const std::shared_ptr<int>& ptr)
445
+ {
446
+ return *ptr;
447
+ }
448
+
408
449
  int updatePointerValue(std::shared_ptr<int> ptr)
409
450
  {
410
451
  *ptr = *ptr + 1;
@@ -416,13 +457,27 @@ TESTCASE(PointerToInt)
416
457
  {
417
458
  Module m = define_module("SharedPtrInt").
418
459
  define_module_function("create_pointer", &createPointer).
419
- define_module_function("get_pointer_value", &getPointerValue);
460
+ define_module_function("create_const_pointer", &createConstPointer).
461
+ define_module_function("get_pointer_value", &getPointerValue).
462
+ define_module_function("get_const_pointer_value", &getConstPointerValue);
420
463
 
421
464
  std::string code = R"(ptr = create_pointer(44)
422
465
  get_pointer_value(ptr))";
423
466
 
424
467
  Object result = m.instance_eval(code);
425
468
  ASSERT_EQUAL(44, detail::From_Ruby<int>().convert(result.value()));
469
+
470
+ code = R"(ptr = create_const_pointer(45)
471
+ get_const_pointer_value(ptr))";
472
+
473
+ result = m.instance_eval(code);
474
+ ASSERT_EQUAL(45, detail::From_Ruby<int>().convert(result.value()));
475
+
476
+ code = R"(ptr = create_const_pointer(46)
477
+ get_pointer_value(ptr))";
478
+
479
+ result = m.instance_eval(code);
480
+ ASSERT_EQUAL(46, detail::From_Ruby<int>().convert(result.value()));
426
481
  }
427
482
 
428
483
  TESTCASE(CreatePointerToInt)
@@ -430,10 +485,8 @@ TESTCASE(CreatePointerToInt)
430
485
  Module m = define_module("CreatePointerToInt").
431
486
  define_module_function("get_pointer_value", &getPointerValue);
432
487
 
433
- define_shared_ptr<int>("SharedPtrInt");
434
-
435
488
  std::string code = R"(buffer = Rice::Buffer≺int≻.new(45)
436
- ptr = Std::SharedPtrInt.new(buffer.release)
489
+ ptr = Std::SharedPtr≺int≻.new(buffer.release)
437
490
  get_pointer_value(ptr))";
438
491
 
439
492
  Object result = m.instance_eval(code);
@@ -445,8 +498,6 @@ TESTCASE(UpdatePointerToInt)
445
498
  Module m = define_module("UpdatePointerToInt").
446
499
  define_module_function("update_pointer_value", &updatePointerValue);
447
500
 
448
- define_shared_ptr<int>();
449
-
450
501
  std::string code = R"(buffer = Rice::Buffer≺int≻.new(45)
451
502
  ptr = Std::SharedPtr≺int≻.new(buffer.release)
452
503
  update_pointer_value(ptr))";
@@ -458,13 +509,101 @@ TESTCASE(UpdatePointerToInt)
458
509
  TESTCASE(ReadPointerToInt)
459
510
  {
460
511
  Module m = define_module("ReadPointerToInt").
461
- define_module_function("create_pointer", &createPointer);
512
+ define_module_function("create_pointer", &createPointer);
462
513
 
463
514
  std::string code = R"(ptr = create_pointer(50)
464
- ptr.buffer.to_ary(1))";
515
+ ptr.get.buffer.to_ary(1))";
465
516
 
466
517
  Array array = m.instance_eval(code);
467
518
  std::vector<int> actual = array.to_vector<int>();
468
- std::vector<int> expected { 50 };
519
+ std::vector<int> expected{ 50 };
469
520
  ASSERT_EQUAL(expected, actual);
521
+ }
522
+
523
+ TESTCASE(AttributeForwarding)
524
+ {
525
+ Factory::reset();
526
+ MyClass::reset();
527
+
528
+ Module m = define_module("TestingModule");
529
+
530
+ // Test read-only attribute
531
+ std::string code = R"(factory = Factory.new
532
+ ptr = factory.share
533
+ ptr.name)";
534
+
535
+ Object result = m.module_eval(code);
536
+ ASSERT_EQUAL("default", detail::From_Ruby<std::string>().convert(result));
537
+
538
+ // Test read/write attribute - read
539
+ code = R"(factory = Factory.new
540
+ ptr = factory.share
541
+ ptr.threshold)";
542
+
543
+ result = m.module_eval(code);
544
+ ASSERT_EQUAL(0, detail::From_Ruby<int>().convert(result));
545
+
546
+ // Test read/write attribute - write and read back
547
+ code = R"(factory = Factory.new
548
+ ptr = factory.share
549
+ ptr.threshold = 42
550
+ ptr.threshold)";
551
+
552
+ result = m.module_eval(code);
553
+ ASSERT_EQUAL(42, detail::From_Ruby<int>().convert(result));
554
+ }
555
+
556
+ TESTCASE(InheritedForwarding)
557
+ {
558
+ Factory::reset();
559
+ MyClass::reset();
560
+
561
+ Module m = define_module("TestingModule");
562
+
563
+ // Test inherited method from MyClass via forwarding
564
+ std::string code = R"(factory = Factory.new
565
+ $ptr = factory.share_inherited
566
+ $ptr.set_flag(99))";
567
+
568
+ m.module_eval(code);
569
+
570
+ // Verify via C++ that set_flag worked
571
+ std::shared_ptr<MyClassInherited>* ptr = detail::From_Ruby<std::shared_ptr<MyClassInherited>*>().convert(
572
+ m.module_eval("$ptr"));
573
+ ASSERT_EQUAL(99, (*ptr)->flag);
574
+
575
+ // Test inherited read-only attribute from MyClass
576
+ code = R"(factory = Factory.new
577
+ ptr = factory.share_inherited
578
+ ptr.name)";
579
+
580
+ Object result = m.module_eval(code);
581
+ ASSERT_EQUAL("default", detail::From_Ruby<std::string>().convert(result));
582
+
583
+ // Test inherited read/write attribute from MyClass
584
+ code = R"(factory = Factory.new
585
+ ptr = factory.share_inherited
586
+ ptr.threshold = 77
587
+ ptr.threshold)";
588
+
589
+ result = m.module_eval(code);
590
+ ASSERT_EQUAL(77, detail::From_Ruby<int>().convert(result));
591
+
592
+ // Test own method on MyClassInherited via forwarding
593
+ code = R"(factory = Factory.new
594
+ ptr = factory.share_inherited
595
+ ptr.set_extra(123)
596
+ ptr.extra)";
597
+
598
+ result = m.module_eval(code);
599
+ ASSERT_EQUAL(123, detail::From_Ruby<int>().convert(result));
600
+
601
+ // Test own attribute on MyClassInherited via forwarding
602
+ code = R"(factory = Factory.new
603
+ ptr = factory.share_inherited
604
+ ptr.extra = 456
605
+ ptr.extra)";
606
+
607
+ result = m.module_eval(code);
608
+ ASSERT_EQUAL(456, detail::From_Ruby<int>().convert(result));
470
609
  }
@@ -93,11 +93,13 @@ TESTCASE(std_string_view_from_ruby_refefence)
93
93
  }
94
94
 
95
95
  namespace {
96
- std::string_view testStringViewReturn(Object self) {
96
+ std::string_view testStringViewReturn(Object)
97
+ {
97
98
  return "test";
98
99
  }
99
100
  }
100
101
 
101
- TESTCASE(use_string_view_in_wrapped_function) {
102
+ TESTCASE(use_string_view_in_wrapped_function)
103
+ {
102
104
  define_global_function("test_string_view_return", &testStringViewReturn);
103
105
  }
@@ -94,7 +94,7 @@ TESTCASE(TupleToRuby)
94
94
  ASSERT_EQUAL(1i, detail::From_Ruby<std::complex<double>>().convert(result[1].value()));
95
95
 
96
96
  std::vector<int> converted = detail::From_Ruby<std::vector<int>>().convert(result[2].value());
97
- ASSERT_EQUAL(3, converted.size());
97
+ ASSERT_EQUAL(3u, converted.size());
98
98
 
99
99
  ASSERT_EQUAL(3.3, detail::From_Ruby<double>().convert(result[3].value()));
100
100
  ASSERT_EQUAL(Qtrue, result[4].value());