rice 4.6.1 → 4.7.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.
Files changed (187) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +38 -0
  3. data/CMakeLists.txt +0 -4
  4. data/Rakefile +2 -8
  5. data/bin/rice-doc.rb +211 -0
  6. data/bin/rice-rbs.rb +92 -0
  7. data/include/rice/rice.hpp +4694 -3704
  8. data/include/rice/stl.hpp +840 -294
  9. data/lib/rice/doc/cpp_reference.rb +166 -0
  10. data/lib/rice/doc/doxygen.rb +294 -0
  11. data/lib/rice/doc/mkdocs.rb +298 -0
  12. data/lib/rice/doc/rice.rb +29 -0
  13. data/lib/rice/doc/ruby.rb +37 -0
  14. data/lib/rice/doc.rb +5 -0
  15. data/lib/{make_rice_headers.rb → rice/make_rice_headers.rb} +3 -0
  16. data/lib/rice/native.rb +18 -0
  17. data/lib/rice/native_registry.rb +21 -0
  18. data/lib/rice/parameter.rb +7 -0
  19. data/lib/rice/rbs.rb +104 -0
  20. data/lib/rice/version.rb +1 -1
  21. data/lib/rice.rb +4 -0
  22. data/lib/rubygems/cmake_builder.rb +24 -27
  23. data/rice/Arg.hpp +4 -4
  24. data/rice/Arg.ipp +4 -4
  25. data/rice/Buffer.hpp +32 -28
  26. data/rice/Buffer.ipp +306 -178
  27. data/rice/Data_Object.ipp +136 -88
  28. data/rice/Data_Type.hpp +5 -7
  29. data/rice/Data_Type.ipp +48 -29
  30. data/rice/Enum.ipp +15 -21
  31. data/rice/Function.hpp +17 -0
  32. data/rice/Function.ipp +13 -0
  33. data/rice/Pointer.hpp +15 -0
  34. data/rice/Pointer.ipp +49 -0
  35. data/rice/Return.hpp +1 -1
  36. data/rice/Return.ipp +2 -2
  37. data/rice/api.hpp +30 -0
  38. data/rice/cpp_api/Array.hpp +4 -4
  39. data/rice/cpp_api/Array.ipp +50 -5
  40. data/rice/cpp_api/Class.hpp +0 -5
  41. data/rice/cpp_api/Class.ipp +19 -0
  42. data/rice/cpp_api/Hash.ipp +20 -0
  43. data/rice/cpp_api/Module.hpp +6 -3
  44. data/rice/cpp_api/Module.ipp +49 -11
  45. data/rice/cpp_api/Object.ipp +31 -2
  46. data/rice/cpp_api/String.hpp +1 -2
  47. data/rice/cpp_api/String.ipp +21 -1
  48. data/rice/cpp_api/Struct.ipp +5 -0
  49. data/rice/cpp_api/Symbol.ipp +43 -0
  50. data/rice/cpp_api/shared_methods.hpp +12 -12
  51. data/rice/detail/MethodInfo.hpp +4 -2
  52. data/rice/detail/MethodInfo.ipp +19 -3
  53. data/rice/detail/ModuleRegistry.hpp +18 -0
  54. data/rice/detail/ModuleRegistry.ipp +25 -0
  55. data/rice/detail/Native.hpp +45 -2
  56. data/rice/detail/Native.ipp +196 -6
  57. data/rice/detail/NativeAttributeGet.hpp +9 -4
  58. data/rice/detail/NativeAttributeGet.ipp +65 -11
  59. data/rice/detail/NativeAttributeSet.hpp +4 -0
  60. data/rice/detail/NativeAttributeSet.ipp +30 -2
  61. data/rice/detail/NativeCallbackFFI.ipp +2 -2
  62. data/rice/detail/NativeCallbackSimple.ipp +1 -1
  63. data/rice/detail/NativeFunction.hpp +11 -49
  64. data/rice/detail/NativeFunction.ipp +82 -379
  65. data/rice/detail/NativeInvoker.hpp +74 -0
  66. data/rice/detail/NativeInvoker.ipp +197 -0
  67. data/rice/detail/NativeIterator.hpp +4 -0
  68. data/rice/detail/NativeIterator.ipp +19 -0
  69. data/rice/detail/NativeMethod.hpp +97 -0
  70. data/rice/detail/NativeMethod.ipp +332 -0
  71. data/rice/detail/NativeProc.hpp +51 -0
  72. data/rice/detail/NativeProc.ipp +133 -0
  73. data/rice/detail/NativeRegistry.hpp +8 -0
  74. data/rice/detail/NativeRegistry.ipp +26 -0
  75. data/rice/detail/Parameter.hpp +47 -0
  76. data/rice/detail/Parameter.ipp +105 -0
  77. data/rice/detail/Proc.ipp +14 -13
  78. data/rice/detail/Registries.hpp +1 -0
  79. data/rice/detail/RubyType.hpp +0 -2
  80. data/rice/detail/RubyType.ipp +15 -33
  81. data/rice/detail/Type.hpp +44 -8
  82. data/rice/detail/Type.ipp +151 -49
  83. data/rice/detail/TypeRegistry.hpp +3 -0
  84. data/rice/detail/TypeRegistry.ipp +17 -27
  85. data/rice/detail/Types.ipp +430 -0
  86. data/rice/detail/Wrapper.hpp +12 -0
  87. data/rice/detail/Wrapper.ipp +45 -2
  88. data/rice/detail/from_ruby.ipp +567 -1073
  89. data/rice/detail/ruby.hpp +1 -0
  90. data/rice/detail/to_ruby.ipp +4 -635
  91. data/rice/libc/file.ipp +3 -6
  92. data/rice/rice.hpp +22 -12
  93. data/rice/rice_api/Arg.hpp +7 -0
  94. data/rice/rice_api/Arg.ipp +9 -0
  95. data/rice/rice_api/ModuleRegistry.hpp +7 -0
  96. data/rice/rice_api/ModuleRegistry.ipp +10 -0
  97. data/rice/rice_api/Native.hpp +7 -0
  98. data/rice/rice_api/Native.ipp +52 -0
  99. data/rice/rice_api/NativeRegistry.hpp +7 -0
  100. data/rice/rice_api/NativeRegistry.ipp +21 -0
  101. data/rice/rice_api/Parameter.hpp +7 -0
  102. data/rice/rice_api/Parameter.ipp +11 -0
  103. data/rice/rice_api/Registries.hpp +6 -0
  104. data/rice/rice_api/Registries.ipp +12 -0
  105. data/rice/rice_api/TypeRegistry.hpp +7 -0
  106. data/rice/rice_api/TypeRegistry.ipp +10 -0
  107. data/rice/stl/complex.ipp +35 -0
  108. data/rice/stl/exception.ipp +20 -7
  109. data/rice/stl/filesystem.hpp +6 -0
  110. data/rice/stl/filesystem.ipp +34 -0
  111. data/rice/stl/map.ipp +13 -21
  112. data/rice/stl/monostate.ipp +37 -1
  113. data/rice/stl/multimap.ipp +17 -24
  114. data/rice/stl/optional.ipp +47 -2
  115. data/rice/stl/pair.ipp +23 -58
  116. data/rice/stl/reference_wrapper.ipp +22 -1
  117. data/rice/stl/set.ipp +17 -9
  118. data/rice/stl/shared_ptr.ipp +44 -17
  119. data/rice/stl/string.ipp +175 -7
  120. data/rice/stl/string_view.ipp +23 -0
  121. data/rice/stl/tuple.ipp +38 -9
  122. data/rice/stl/unique_ptr.ipp +46 -2
  123. data/rice/stl/unordered_map.ipp +13 -21
  124. data/rice/stl/variant.ipp +47 -11
  125. data/rice/stl/vector.ipp +183 -104
  126. data/rice/stl.hpp +1 -0
  127. data/rice/traits/function_traits.hpp +2 -2
  128. data/rice/traits/method_traits.hpp +5 -16
  129. data/rice/traits/rice_traits.hpp +24 -4
  130. data/rice.gemspec +10 -22
  131. data/test/embed_ruby.cpp +0 -3
  132. data/test/test_Array.cpp +38 -38
  133. data/test/test_Attribute.cpp +187 -2
  134. data/test/test_Buffer.cpp +302 -26
  135. data/test/test_Callback.cpp +2 -3
  136. data/test/test_Class.cpp +5 -5
  137. data/test/test_Data_Object.cpp +1 -56
  138. data/test/test_Data_Type.cpp +20 -30
  139. data/test/test_Enum.cpp +4 -46
  140. data/test/test_From_Ruby.cpp +89 -82
  141. data/test/test_GVL.cpp +109 -0
  142. data/test/test_Iterator.cpp +1 -1
  143. data/test/test_Keep_Alive_No_Wrapper.cpp +5 -3
  144. data/test/test_Module.cpp +8 -9
  145. data/test/test_Object.cpp +1 -1
  146. data/test/test_Overloads.cpp +58 -10
  147. data/test/test_Stl_Map.cpp +8 -8
  148. data/test/test_Stl_Multimap.cpp +4 -4
  149. data/test/test_Stl_Pair.cpp +5 -3
  150. data/test/test_Stl_SharedPtr.cpp +24 -12
  151. data/test/test_Stl_String_View.cpp +10 -0
  152. data/test/test_Stl_Tuple.cpp +1 -1
  153. data/test/test_Stl_UniquePtr.cpp +8 -0
  154. data/test/test_Stl_Unordered_Map.cpp +9 -9
  155. data/test/test_Stl_Variant.cpp +9 -3
  156. data/test/test_Stl_Vector.cpp +118 -13
  157. data/test/test_Symbol.cpp +12 -0
  158. data/test/test_To_Ruby.cpp +35 -28
  159. data/test/test_Type.cpp +256 -53
  160. data/test/unittest.hpp +35 -0
  161. metadata +52 -34
  162. data/rice/Init.hpp +0 -8
  163. data/rice/Init.ipp +0 -8
  164. data/rice/detail/RubyFunction.hpp +0 -31
  165. data/rice/detail/RubyFunction.ipp +0 -77
  166. data/sample/callbacks/extconf.rb +0 -5
  167. data/sample/callbacks/sample_callbacks.cpp +0 -35
  168. data/sample/callbacks/test.rb +0 -28
  169. data/sample/enum/extconf.rb +0 -5
  170. data/sample/enum/sample_enum.cpp +0 -40
  171. data/sample/enum/test.rb +0 -8
  172. data/sample/inheritance/animals.cpp +0 -82
  173. data/sample/inheritance/extconf.rb +0 -5
  174. data/sample/inheritance/test.rb +0 -7
  175. data/sample/map/extconf.rb +0 -5
  176. data/sample/map/map.cpp +0 -73
  177. data/sample/map/test.rb +0 -7
  178. data/test/ext/t1/Foo.hpp +0 -10
  179. data/test/ext/t1/extconf.rb +0 -4
  180. data/test/ext/t1/t1.cpp +0 -13
  181. data/test/ext/t2/extconf.rb +0 -4
  182. data/test/ext/t2/t2.cpp +0 -11
  183. data/test/ruby/test_callbacks_sample.rb +0 -28
  184. data/test/ruby/test_multiple_extensions.rb +0 -18
  185. data/test/ruby/test_multiple_extensions_same_class.rb +0 -14
  186. data/test/ruby/test_multiple_extensions_with_inheritance.rb +0 -20
  187. /data/test/{test_Stl_Type.cpp → test_Stl_Type_Info.cpp} +0 -0
data/rice/Data_Object.ipp CHANGED
@@ -6,9 +6,19 @@ namespace Rice
6
6
  template <typename T>
7
7
  Exception create_type_exception(VALUE value)
8
8
  {
9
- return Exception(rb_eTypeError, "Wrong argument type. Expected: %s. Received: %s.",
10
- detail::protect(rb_class2name, Data_Type<T>::klass().value()),
11
- detail::protect(rb_obj_classname, value));
9
+ if (Data_Type<T>::is_bound())
10
+ {
11
+ return Exception(rb_eTypeError, "Wrong argument type. Expected %s. Received %s.",
12
+ detail::protect(rb_class2name, Data_Type<T>::klass().value()),
13
+ detail::protect(rb_obj_classname, value));
14
+ }
15
+ else
16
+ {
17
+ detail::TypeMapper<T> typeMapper;
18
+ return Exception(rb_eTypeError, "Wrong argument type. Expected %s. Received %s.",
19
+ typeMapper.simplifiedName().c_str(),
20
+ detail::protect(rb_obj_classname, value));
21
+ }
12
22
  }
13
23
 
14
24
  template<typename T>
@@ -102,6 +112,12 @@ namespace Rice::detail
102
112
  "Please include rice/stl.hpp header for STL support");
103
113
 
104
114
  public:
115
+ To_Ruby() = default;
116
+
117
+ explicit To_Ruby(Arg* arg) : arg_(arg)
118
+ {
119
+ }
120
+
105
121
  template<typename U>
106
122
  VALUE convert(U& data)
107
123
  {
@@ -123,6 +139,9 @@ namespace Rice::detail
123
139
  // matched <typename T> thus we have to tell wrap to copy the reference we are sending to it
124
140
  return detail::wrap(rubyTypeInfo.first, rubyTypeInfo.second, data, true);
125
141
  }
142
+
143
+ private:
144
+ Arg* arg_ = nullptr;
126
145
  };
127
146
 
128
147
  template <typename T>
@@ -141,7 +160,7 @@ namespace Rice::detail
141
160
  public:
142
161
  To_Ruby() = default;
143
162
 
144
- explicit To_Ruby(Return * returnInfo) : returnInfo_(returnInfo)
163
+ explicit To_Ruby(Arg* arg) : arg_(arg)
145
164
  {
146
165
  }
147
166
 
@@ -152,19 +171,45 @@ namespace Rice::detail
152
171
  // child class. Lookup the correct type so we return an instance of the correct Ruby class
153
172
  std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType<T>(data);
154
173
 
155
- bool isOwner = (this->returnInfo_ && this->returnInfo_->isOwner());
174
+ bool isOwner = (this->arg_ && this->arg_->isOwner());
156
175
  return detail::wrap(rubyTypeInfo.first, rubyTypeInfo.second, data, isOwner);
157
176
  }
158
177
  private:
159
- Return* returnInfo_ = nullptr;
178
+ Arg* arg_ = nullptr;
179
+ };
180
+
181
+ template <typename T, int N>
182
+ class To_Ruby<T[N]>
183
+ {
184
+ static_assert(!std::is_same_v<T, std::map<T, T>> && !std::is_same_v<T, std::unordered_map<T, T>> &&
185
+ !std::is_same_v<T, std::monostate> && !std::is_same_v<T, std::multimap<T, T>> &&
186
+ !std::is_same_v<T, std::optional<T>> && !std::is_same_v<T, std::pair<T, T>> &&
187
+ !std::is_same_v<T, std::set<T>> && !std::is_same_v<T, std::string> &&
188
+ !std::is_same_v<T, std::vector<T>>,
189
+ "Please include rice/stl.hpp header for STL support");
190
+
191
+ public:
192
+ To_Ruby() = default;
193
+
194
+ explicit To_Ruby(Arg* arg) : arg_(arg)
195
+ {
196
+ }
197
+
198
+ template<typename U>
199
+ VALUE convert(U data[N])
200
+ {
201
+ Buffer<T> buffer(data, N);
202
+ Data_Object<Buffer<T>> dataObject(std::move(buffer));
203
+ return dataObject.value();
204
+ }
205
+
206
+ private:
207
+ Arg* arg_ = nullptr;
160
208
  };
161
209
 
162
210
  template <typename T>
163
211
  class To_Ruby<T*>
164
212
  {
165
- static_assert(!std::is_fundamental_v<intrinsic_type<T>>,
166
- "Data_Object cannot be used with fundamental types");
167
-
168
213
  static_assert(!std::is_same_v<T, std::map<T, T>> && !std::is_same_v<T, std::unordered_map<T, T>> &&
169
214
  !std::is_same_v<T, std::monostate> && !std::is_same_v<T, std::multimap<T, T>> &&
170
215
  !std::is_same_v<T, std::optional<T>> && !std::is_same_v<T, std::pair<T, T>> &&
@@ -175,25 +220,24 @@ namespace Rice::detail
175
220
  public:
176
221
  To_Ruby() = default;
177
222
 
178
- explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
223
+ explicit To_Ruby(Arg* arg) : arg_(arg)
179
224
  {
180
225
  }
181
226
 
182
227
  template<typename U>
183
228
  VALUE convert(U* data)
184
229
  {
185
- bool isOwner = this->returnInfo_ && this->returnInfo_->isOwner();
230
+ bool isOwner = this->arg_ && this->arg_->isOwner();
231
+ bool isBuffer = this->arg_ && this->arg_->isBuffer();
186
232
 
187
233
  if (data == nullptr)
188
234
  {
189
235
  return Qnil;
190
236
  }
191
- else if (this->returnInfo_ && this->returnInfo_->isArray())
237
+ else if (std::is_fundamental_v<std::remove_pointer_t<T>> || isBuffer)
192
238
  {
193
- using Buffer_T = Buffer<T>;
194
- Buffer_T buffer((T*)data);
195
- buffer.setOwner(isOwner);
196
- return detail::wrap(Data_Type<Buffer_T>::klass(), Data_Type<Buffer_T>::ruby_data_type(), buffer, true);
239
+ using Pointer_T = Pointer<remove_cv_recursive_t<U>>;
240
+ return detail::wrap(Data_Type<Pointer_T>::klass(), Data_Type<Pointer_T>::ruby_data_type(), data, isOwner);
197
241
  }
198
242
  else
199
243
  {
@@ -205,15 +249,12 @@ namespace Rice::detail
205
249
  }
206
250
 
207
251
  private:
208
- Return* returnInfo_ = nullptr;
252
+ Arg* arg_ = nullptr;
209
253
  };
210
254
 
211
255
  template <typename T>
212
- class To_Ruby<T*&>
256
+ class To_Ruby<T*&>
213
257
  {
214
- static_assert(!std::is_fundamental_v<intrinsic_type<T>>,
215
- "Data_Object cannot be used with fundamental types");
216
-
217
258
  static_assert(!std::is_same_v<T, std::map<T, T>> && !std::is_same_v<T, std::unordered_map<T, T>> &&
218
259
  !std::is_same_v<T, std::monostate> && !std::is_same_v<T, std::multimap<T, T>> &&
219
260
  !std::is_same_v<T, std::optional<T>> && !std::is_same_v<T, std::pair<T, T>> &&
@@ -224,25 +265,29 @@ namespace Rice::detail
224
265
  public:
225
266
  To_Ruby() = default;
226
267
 
227
- explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
268
+ explicit To_Ruby(Arg* arg) : arg_(arg)
228
269
  {
229
270
  }
230
271
 
231
272
  template<typename U>
232
273
  VALUE convert(U* data)
233
274
  {
234
- bool isOwner = this->returnInfo_ && this->returnInfo_->isOwner();
235
-
275
+ bool isOwner = this->arg_ && this->arg_->isOwner();
276
+ bool isBuffer = this->arg_ && this->arg_->isBuffer();
277
+
236
278
  if (data == nullptr)
237
279
  {
238
280
  return Qnil;
239
281
  }
240
- else if (this->returnInfo_ && this->returnInfo_->isArray())
282
+ else if constexpr (std::is_const_v<U>)
283
+ {
284
+ std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType(*data);
285
+ return detail::wrap(rubyTypeInfo.first, rubyTypeInfo.second, data, isOwner);
286
+ }
287
+ else if (std::is_fundamental_v<T> || isBuffer)
241
288
  {
242
- using Buffer_T = Buffer<intrinsic_type<T>>;
243
- Buffer_T buffer((T*)data);
244
- buffer.setOwner(isOwner);
245
- return detail::wrap(Data_Type<Buffer_T>::klass(), Data_Type<Buffer_T>::ruby_data_type(), buffer, true);
289
+ using Pointer_T = Pointer<remove_cv_recursive_t<U>>;
290
+ return detail::wrap(Data_Type<Pointer_T>::klass(), Data_Type<Pointer_T>::ruby_data_type(), data, isOwner);
246
291
  }
247
292
  else
248
293
  {
@@ -254,26 +299,16 @@ namespace Rice::detail
254
299
  }
255
300
 
256
301
  private:
257
- Return* returnInfo_ = nullptr;
302
+ Arg* arg_ = nullptr;
258
303
  };
259
304
 
260
305
  template <typename T>
261
306
  class To_Ruby<T**>
262
307
  {
263
- static_assert(!std::is_fundamental_v<intrinsic_type<T>>,
264
- "Data_Object cannot be used with fundamental types");
265
-
266
- static_assert(!std::is_same_v<T, std::map<T, T>> && !std::is_same_v<T, std::unordered_map<T, T>> &&
267
- !std::is_same_v<T, std::monostate> && !std::is_same_v<T, std::multimap<T, T>> &&
268
- !std::is_same_v<T, std::optional<T>> && !std::is_same_v<T, std::pair<T, T>> &&
269
- !std::is_same_v<T, std::set<T>> && !std::is_same_v<T, std::string> &&
270
- !std::is_same_v<T, std::vector<T>>,
271
- "Please include rice/stl.hpp header for STL support");
272
-
273
308
  public:
274
309
  To_Ruby() = default;
275
310
 
276
- explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
311
+ explicit To_Ruby(Arg* arg) : arg_(arg)
277
312
  {
278
313
  }
279
314
 
@@ -282,11 +317,9 @@ namespace Rice::detail
282
317
  {
283
318
  if (data)
284
319
  {
285
- bool isOwner = this->returnInfo_ && this->returnInfo_->isOwner();
286
- Buffer<T*> buffer((T**)data);
287
- buffer.setOwner(isOwner);
288
- using Buffer_T = Buffer<intrinsic_type<T>*>;
289
- return detail::wrap(Data_Type<Buffer_T>::klass(), Data_Type<Buffer_T>::ruby_data_type(), buffer, true);
320
+ bool isOwner = this->arg_ && this->arg_->isOwner();
321
+ using Pointer_T = Pointer<remove_cv_recursive_t<U>*>;
322
+ return detail::wrap(Data_Type<Pointer_T>::klass(), Data_Type<Pointer_T>::ruby_data_type(), data, isOwner);
290
323
  }
291
324
  else
292
325
  {
@@ -295,7 +328,7 @@ namespace Rice::detail
295
328
  }
296
329
 
297
330
  private:
298
- Return* returnInfo_ = nullptr;
331
+ Arg* arg_ = nullptr;
299
332
  };
300
333
 
301
334
  template<typename T>
@@ -448,13 +481,9 @@ namespace Rice::detail
448
481
 
449
482
  // 99% of the time a T* represents a wrapped C++ object that we want to call methods on. However, T*
450
483
  // could also be a pointer to an array of T objects, so T[]. OpenCV for example has API calls like this.
451
- // In that case, the Ruby VALUE will be a Buffer<T> instance
452
484
  template<typename T>
453
485
  class From_Ruby<T*>
454
486
  {
455
- static_assert(!std::is_fundamental_v<intrinsic_type<T>>,
456
- "Data_Object cannot be used with fundamental types");
457
-
458
487
  static_assert(!std::is_same_v<T, std::map<T, T>> && !std::is_same_v<T, std::unordered_map<T, T>> &&
459
488
  !std::is_same_v<T, std::monostate> && !std::is_same_v<T, std::multimap<T, T>> &&
460
489
  !std::is_same_v<T, std::optional<T>> && !std::is_same_v<T, std::pair<T, T>> &&
@@ -463,6 +492,7 @@ namespace Rice::detail
463
492
  "Please include rice/stl.hpp header for STL support");
464
493
 
465
494
  using Intrinsic_T = intrinsic_type<T>;
495
+ using Pointer_T = Pointer<remove_cv_recursive_t<T>>;
466
496
 
467
497
  public:
468
498
  From_Ruby() = default;
@@ -473,24 +503,23 @@ namespace Rice::detail
473
503
 
474
504
  Convertible is_convertible(VALUE value)
475
505
  {
506
+ bool isBuffer = this->arg_->isBuffer();
507
+
476
508
  switch (rb_type(value))
477
509
  {
510
+ case RUBY_T_NIL:
511
+ return Convertible::Exact;
512
+ break;
478
513
  case RUBY_T_DATA:
479
- if (this->arg_ && this->arg_->isArray())
514
+ if (Data_Type<T>::is_descendant(value) && !isBuffer)
480
515
  {
481
- return Data_Type<Buffer<T>>::is_descendant(value) ? Convertible::Exact : Convertible::None;
516
+ return Convertible::Exact;
482
517
  }
483
- else
518
+ else if (Data_Type<Pointer_T>::is_descendant(value))
484
519
  {
485
- return Data_Type<T>::is_descendant(value) ? Convertible::Exact : Convertible::None;
520
+ return Convertible::Exact;
486
521
  }
487
- break;
488
- case RUBY_T_NIL:
489
- return Convertible::Exact;
490
- break;
491
- case RUBY_T_ARRAY:
492
- return Convertible::Exact;
493
- break;
522
+ [[fallthrough]];
494
523
  default:
495
524
  return Convertible::None;
496
525
  }
@@ -498,6 +527,9 @@ namespace Rice::detail
498
527
 
499
528
  T* convert(VALUE value)
500
529
  {
530
+ bool isOwner = this->arg_ && this->arg_->isOwner();
531
+ bool isBuffer = this->arg_ && this->arg_->isBuffer();
532
+
501
533
  switch (rb_type(value))
502
534
  {
503
535
  case RUBY_T_NIL:
@@ -507,20 +539,26 @@ namespace Rice::detail
507
539
  }
508
540
  case RUBY_T_DATA:
509
541
  {
510
- if (this->arg_ && this->arg_->isArray())
542
+ if (Data_Type<T>::is_descendant(value) && !isBuffer)
511
543
  {
512
- using Buffer_T = Buffer<Intrinsic_T>;
513
- Buffer_T* buffer = detail::unwrap<Buffer_T>(value, Data_Type<Buffer_T>::ruby_data_type(), this->arg_ && this->arg_->isOwner());
514
- return buffer->ptr();
544
+ return detail::unwrap<Intrinsic_T>(value, Data_Type<Intrinsic_T>::ruby_data_type(), isOwner);
515
545
  }
516
- else
546
+ else if (Data_Type<Pointer_T>::is_descendant(value))
517
547
  {
518
- return detail::unwrap<Intrinsic_T>(value, Data_Type<Intrinsic_T>::ruby_data_type(), this->arg_ && this->arg_->isOwner());
548
+ return detail::unwrap<T>(value, Data_Type<Pointer_T>::ruby_data_type(), isOwner);
519
549
  }
550
+ [[fallthrough]];
520
551
  }
521
552
  default:
522
553
  {
523
- throw create_type_exception<Intrinsic_T>(value);
554
+ if (isBuffer || std::is_fundamental_v<T>)
555
+ {
556
+ throw create_type_exception<Pointer_T>(value);
557
+ }
558
+ else
559
+ {
560
+ throw create_type_exception<T>(value);
561
+ }
524
562
  }
525
563
  }
526
564
  }
@@ -532,9 +570,6 @@ namespace Rice::detail
532
570
  template<typename T>
533
571
  class From_Ruby<T*&>
534
572
  {
535
- static_assert(!std::is_fundamental_v<intrinsic_type<T>>,
536
- "Data_Object cannot be used with fundamental types");
537
-
538
573
  static_assert(!std::is_same_v<T, std::map<T, T>> && !std::is_same_v<T, std::unordered_map<T, T>> &&
539
574
  !std::is_same_v<T, std::monostate> && !std::is_same_v<T, std::multimap<T, T>> &&
540
575
  !std::is_same_v<T, std::optional<T>> && !std::is_same_v<T, std::pair<T, T>> &&
@@ -582,9 +617,6 @@ namespace Rice::detail
582
617
  template<typename T>
583
618
  class From_Ruby<T**>
584
619
  {
585
- static_assert(!std::is_fundamental_v<intrinsic_type<T>>,
586
- "Data_Object cannot be used with fundamental types");
587
-
588
620
  static_assert(!std::is_same_v<T, std::map<T, T>> && !std::is_same_v<T, std::unordered_map<T, T>> &&
589
621
  !std::is_same_v<T, std::monostate> && !std::is_same_v<T, std::multimap<T, T>> &&
590
622
  !std::is_same_v<T, std::optional<T>> && !std::is_same_v<T, std::pair<T, T>> &&
@@ -593,6 +625,7 @@ namespace Rice::detail
593
625
  "Please include rice/stl.hpp header for STL support");
594
626
 
595
627
  using Intrinsic_T = intrinsic_type<T>;
628
+ using Pointer_T = Pointer<remove_cv_recursive_t<T>*>;
596
629
  public:
597
630
  From_Ruby() = default;
598
631
 
@@ -602,17 +635,19 @@ namespace Rice::detail
602
635
 
603
636
  Convertible is_convertible(VALUE value)
604
637
  {
638
+ bool isBuffer = this->arg_ && this->arg_->isBuffer();
639
+
605
640
  switch (rb_type(value))
606
641
  {
607
- case RUBY_T_DATA:
608
- return Data_Type<Buffer<T*>>::is_descendant(value) ? Convertible::Exact : Convertible::None;
609
- break;
610
642
  case RUBY_T_NIL:
611
643
  return Convertible::Exact;
612
644
  break;
613
- case RUBY_T_ARRAY:
614
- return Convertible::Exact;
615
- break;
645
+ case RUBY_T_DATA:
646
+ if (Data_Type<Pointer_T>::is_descendant(value) && isBuffer)
647
+ {
648
+ return Convertible::Exact;
649
+ }
650
+ [[fallthrough]];
616
651
  default:
617
652
  return Convertible::None;
618
653
  }
@@ -620,22 +655,35 @@ namespace Rice::detail
620
655
 
621
656
  T** convert(VALUE value)
622
657
  {
658
+ bool isOwner = this->arg_ && this->arg_->isOwner();
659
+ bool isBuffer = this->arg_ && this->arg_->isBuffer();
660
+
623
661
  switch (rb_type(value))
624
662
  {
625
- case RUBY_T_DATA:
626
- {
627
- Buffer<Intrinsic_T*>* buffer = detail::unwrap<Buffer<Intrinsic_T*>>(value, Data_Type<Buffer<Intrinsic_T*>>::ruby_data_type(), false);
628
- return buffer->ptr();
629
- break;
630
- }
631
663
  case RUBY_T_NIL:
632
664
  {
633
665
  return nullptr;
634
666
  break;
635
667
  }
668
+ case RUBY_T_DATA:
669
+ {
670
+ if (Data_Type<Pointer_T>::is_descendant(value) && isBuffer)
671
+ {
672
+ T** result = detail::unwrap<Intrinsic_T*>(value, Data_Type<Pointer_T>::ruby_data_type(), isOwner);
673
+ return result;
674
+ }
675
+ [[fallthrough]];
676
+ }
636
677
  default:
637
678
  {
638
- throw create_type_exception<Intrinsic_T>(value);
679
+ if (isBuffer)
680
+ {
681
+ throw create_type_exception<Pointer_T>(value);
682
+ }
683
+ else
684
+ {
685
+ throw create_type_exception<T**>(value);
686
+ }
639
687
  }
640
688
  }
641
689
  }
data/rice/Data_Type.hpp CHANGED
@@ -12,8 +12,6 @@ namespace Rice
12
12
  template<typename T>
13
13
  class Data_Type : public Class
14
14
  {
15
- static_assert(std::is_same_v<detail::intrinsic_type<T>, T>);
16
-
17
15
  public:
18
16
  using type = T;
19
17
 
@@ -137,10 +135,10 @@ namespace Rice
137
135
  Data_Type<T>& define_iterator(Iterator_Func_T begin, Iterator_Func_T end, std::string name = "each");
138
136
 
139
137
  template <typename Attribute_T>
140
- Data_Type<T>& define_attr(std::string name, Attribute_T attribute, AttrAccess access = AttrAccess::ReadWrite);
138
+ Data_Type<T>& define_attr(std::string name, Attribute_T attribute, AttrAccess access = AttrAccess::ReadWrite, Return returnInfo = Return());
141
139
 
142
140
  template <typename Attribute_T>
143
- Data_Type<T>& define_singleton_attr(std::string name, Attribute_T attribute, AttrAccess access = AttrAccess::ReadWrite);
141
+ Data_Type<T>& define_singleton_attr(std::string name, Attribute_T attribute, AttrAccess access = AttrAccess::ReadWrite, Return returnInfo = Return());
144
142
 
145
143
  #include "cpp_api/shared_methods.hpp"
146
144
  protected:
@@ -163,11 +161,11 @@ namespace Rice
163
161
  template<typename T_, typename Base_T>
164
162
  friend Rice::Data_Type<T_> define_class(char const * name);
165
163
 
166
- template<bool IsMethod, typename Function_T>
167
- void wrap_native_call(VALUE klass, std::string name, Function_T&& function, MethodInfo* methodInfo);
164
+ template<typename Method_T>
165
+ void wrap_native_method(VALUE klass, std::string name, Method_T&& function, MethodInfo* methodInfo);
168
166
 
169
167
  template <typename Attribute_T>
170
- Data_Type<T>& define_attr_internal(VALUE klass, std::string name, Attribute_T attribute, AttrAccess access);
168
+ Data_Type<T>& define_attr_internal(VALUE klass, std::string name, Attribute_T attribute, AttrAccess access, Return returnInfo);
171
169
 
172
170
  private:
173
171
  template<typename T_>
data/rice/Data_Type.ipp CHANGED
@@ -37,7 +37,8 @@ namespace Rice
37
37
  {
38
38
  if (is_bound())
39
39
  {
40
- std::string message = "Type " + detail::typeName(typeid(T)) + " is already bound to a different type";
40
+ detail::TypeMapper<T> typeMapper;
41
+ std::string message = "Type " + typeMapper.name() + " is already bound to a different type";
41
42
  throw std::runtime_error(message.c_str());
42
43
  }
43
44
 
@@ -56,9 +57,6 @@ namespace Rice
56
57
  rb_data_type_->parent = Data_Type<Base_T>::ruby_data_type();
57
58
  }
58
59
 
59
- // Now register with the type registry
60
- detail::Registries::instance.types.add<T>(klass_, rb_data_type_);
61
-
62
60
  auto instances = unbound_instances();
63
61
  for (auto instance: instances)
64
62
  {
@@ -66,7 +64,21 @@ namespace Rice
66
64
  }
67
65
  instances.clear();
68
66
 
69
- return Data_Type<T>();
67
+ // Register with the type registry
68
+ detail::Registries::instance.types.add<T>(klass_, rb_data_type_);
69
+
70
+ // Add a method to get the source C++ class name from Ruby
71
+ Data_Type<T> dataType;
72
+ dataType.define_singleton_method("cpp_class", [](VALUE klass) -> VALUE
73
+ {
74
+ detail::TypeMapper<T> typeMapper;
75
+ std::string cppClassName = typeMapper.simplifiedName();
76
+ Return returnInfo;
77
+ returnInfo.takeOwnership();
78
+ return detail::To_Ruby<char*>(&returnInfo).convert(cppClassName.c_str());
79
+ }, Arg("klass").setValue(), Return().setValue());
80
+
81
+ return dataType;
70
82
  }
71
83
 
72
84
  template<typename T>
@@ -206,8 +218,14 @@ namespace Rice
206
218
  template<typename T>
207
219
  inline bool Data_Type<T>::is_descendant(VALUE value)
208
220
  {
209
- check_is_bound();
210
- return detail::protect(rb_obj_is_kind_of, value, klass_) == Qtrue;
221
+ if (is_bound())
222
+ {
223
+ return detail::protect(rb_obj_is_kind_of, value, klass_) == Qtrue;
224
+ }
225
+ else
226
+ {
227
+ return false;
228
+ }
211
229
  }
212
230
 
213
231
  template<typename T>
@@ -215,7 +233,8 @@ namespace Rice
215
233
  {
216
234
  if (!is_bound())
217
235
  {
218
- std::string message = "Type is not defined with Rice: " + detail::typeName(typeid(T));
236
+ detail::TypeMapper<T> typeMapper;
237
+ std::string message = "Type is not defined with Rice: " + typeMapper.name();
219
238
  throw std::invalid_argument(message.c_str());
220
239
  }
221
240
  }
@@ -312,52 +331,58 @@ namespace Rice
312
331
 
313
332
  template <typename T>
314
333
  template <typename Attribute_T>
315
- inline Data_Type<T>& Data_Type<T>::define_attr(std::string name, Attribute_T attribute, AttrAccess access)
334
+ inline Data_Type<T>& Data_Type<T>::define_attr(std::string name, Attribute_T attribute, AttrAccess access, Return returnInfo)
316
335
  {
317
- return this->define_attr_internal<Attribute_T>(this->klass_, name, std::forward<Attribute_T>(attribute), access);
336
+ return this->define_attr_internal<Attribute_T>(this->klass_, name, std::forward<Attribute_T>(attribute), access, returnInfo);
318
337
  }
319
338
 
320
339
  template <typename T>
321
340
  template <typename Attribute_T>
322
- inline Data_Type<T>& Data_Type<T>::define_singleton_attr(std::string name, Attribute_T attribute, AttrAccess access)
341
+ inline Data_Type<T>& Data_Type<T>::define_singleton_attr(std::string name, Attribute_T attribute, AttrAccess access, Return returnInfo)
323
342
  {
324
343
  VALUE singleton = detail::protect(rb_singleton_class, this->value());
325
- return this->define_attr_internal<Attribute_T>(singleton, name, std::forward<Attribute_T>(attribute), access);
344
+ return this->define_attr_internal<Attribute_T>(singleton, name, std::forward<Attribute_T>(attribute), access, returnInfo);
326
345
  }
327
346
 
328
347
  template <typename T>
329
348
  template <typename Attribute_T>
330
- inline Data_Type<T>& Data_Type<T>::define_attr_internal(VALUE klass, std::string name, Attribute_T attribute, AttrAccess access)
349
+ inline Data_Type<T>& Data_Type<T>::define_attr_internal(VALUE klass, std::string name, Attribute_T attribute, AttrAccess access, Return returnInfo)
331
350
  {
332
351
  using Attr_T = typename detail::attribute_traits<Attribute_T>::attr_type;
333
352
 
334
- // Make sure the Attribute type has been previously seen by Rice
335
- detail::verifyType<Attr_T>();
336
-
337
353
  // Define attribute getter
338
354
  if (access == AttrAccess::ReadWrite || access == AttrAccess::Read)
339
355
  {
340
- detail::NativeAttributeGet<Attribute_T>::define(klass, name, std::forward<Attribute_T>(attribute));
356
+ detail::NativeAttributeGet<Attribute_T>::define(klass, name, std::forward<Attribute_T>(attribute), returnInfo);
341
357
  }
342
358
 
359
+ // Define attribute setter
343
360
  // Define attribute setter
344
361
  if (access == AttrAccess::ReadWrite || access == AttrAccess::Write)
345
362
  {
363
+ // This seems super hacky - must be a better way?
364
+ constexpr bool checkWriteAccess = !std::is_reference_v<Attr_T> &&
365
+ !std::is_pointer_v<Attr_T> &&
366
+ !std::is_fundamental_v<Attr_T> &&
367
+ !std::is_enum_v<Attr_T>;
368
+
346
369
  if constexpr (std::is_const_v<Attr_T>)
347
370
  {
348
371
  throw std::runtime_error("Cannot define attribute writer for a const attribute: " + name);
349
372
  }
350
- else if constexpr (!std::is_fundamental_v<Attr_T> && !std::is_assignable_v<Attr_T, Attr_T>)
373
+ // Attributes are set using assignment operator like this:
374
+ // myInstance.attribute = newvalue
375
+ else if constexpr (checkWriteAccess && !std::is_assignable_v<Attr_T, Attr_T>)
351
376
  {
352
377
  throw std::runtime_error("Cannot define attribute writer for a non assignable attribute: " + name);
353
378
  }
354
- else if constexpr (!std::is_fundamental_v<Attr_T> && !std::is_copy_constructible_v<Attr_T>)
379
+ // From_Ruby returns a copy of the value for non-reference and non-pointers, thus needs to be copy constructable
380
+ else if constexpr (checkWriteAccess && !std::is_copy_constructible_v<Attr_T>)
355
381
  {
356
382
  throw std::runtime_error("Cannot define attribute writer for a non copy constructible attribute: " + name);
357
383
  }
358
384
  else
359
385
  {
360
- // Define native attribute setter
361
386
  detail::NativeAttributeSet<Attribute_T>::define(klass, name, std::forward<Attribute_T>(attribute));
362
387
  }
363
388
  }
@@ -366,15 +391,9 @@ namespace Rice
366
391
  }
367
392
 
368
393
  template <typename T>
369
- template<bool IsMethod, typename Function_T>
370
- inline void Data_Type<T>::wrap_native_call(VALUE klass, std::string name, Function_T&& function, MethodInfo* methodInfo)
394
+ template<typename Method_T>
395
+ inline void Data_Type<T>::wrap_native_method(VALUE klass, std::string name, Method_T&& method, MethodInfo* methodInfo)
371
396
  {
372
- // Make sure the return type and arguments have been previously seen by Rice
373
- using traits = detail::method_traits<Function_T, IsMethod>;
374
- detail::verifyType<typename traits::Return_T>();
375
- detail::verifyTypes<typename traits::Arg_Ts>();
376
-
377
- // Define a NativeFunction to bridge Ruby to C++
378
- detail::NativeFunction<T, Function_T, IsMethod>::define(klass, name, std::forward<Function_T>(function), methodInfo);
397
+ Module::wrap_native_method<T, Method_T>(klass, name, std::forward<Method_T>(method), methodInfo);
379
398
  }
380
399
  }