rice 4.6.1 → 4.7.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 (185) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +31 -0
  3. data/CMakeLists.txt +0 -4
  4. data/Rakefile +2 -8
  5. data/bin/rice-doc.rb +212 -0
  6. data/bin/rice-rbs.rb +93 -0
  7. data/include/rice/rice.hpp +4972 -4015
  8. data/include/rice/stl.hpp +822 -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 +101 -82
  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 +2 -2
  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 +34 -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 -2
  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 +27 -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 +5 -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 +11 -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 +0 -55
  138. data/test/test_Data_Type.cpp +19 -30
  139. data/test/test_Enum.cpp +4 -46
  140. data/test/test_From_Ruby.cpp +88 -81
  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 +3 -3
  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_Tuple.cpp +1 -1
  152. data/test/test_Stl_UniquePtr.cpp +8 -0
  153. data/test/test_Stl_Unordered_Map.cpp +9 -9
  154. data/test/test_Stl_Variant.cpp +9 -3
  155. data/test/test_Stl_Vector.cpp +118 -13
  156. data/test/test_To_Ruby.cpp +35 -28
  157. data/test/test_Type.cpp +256 -53
  158. data/test/unittest.hpp +35 -0
  159. metadata +66 -34
  160. data/rice/Init.hpp +0 -8
  161. data/rice/Init.ipp +0 -8
  162. data/rice/detail/RubyFunction.hpp +0 -31
  163. data/rice/detail/RubyFunction.ipp +0 -77
  164. data/sample/callbacks/extconf.rb +0 -5
  165. data/sample/callbacks/sample_callbacks.cpp +0 -35
  166. data/sample/callbacks/test.rb +0 -28
  167. data/sample/enum/extconf.rb +0 -5
  168. data/sample/enum/sample_enum.cpp +0 -40
  169. data/sample/enum/test.rb +0 -8
  170. data/sample/inheritance/animals.cpp +0 -82
  171. data/sample/inheritance/extconf.rb +0 -5
  172. data/sample/inheritance/test.rb +0 -7
  173. data/sample/map/extconf.rb +0 -5
  174. data/sample/map/map.cpp +0 -73
  175. data/sample/map/test.rb +0 -7
  176. data/test/ext/t1/Foo.hpp +0 -10
  177. data/test/ext/t1/extconf.rb +0 -4
  178. data/test/ext/t1/t1.cpp +0 -13
  179. data/test/ext/t2/extconf.rb +0 -4
  180. data/test/ext/t2/t2.cpp +0 -11
  181. data/test/ruby/test_callbacks_sample.rb +0 -28
  182. data/test/ruby/test_multiple_extensions.rb +0 -18
  183. data/test/ruby/test_multiple_extensions_same_class.rb +0 -14
  184. data/test/ruby/test_multiple_extensions_with_inheritance.rb +0 -20
  185. /data/test/{test_Stl_Type.cpp → test_Stl_Type_Info.cpp} +0 -0
data/rice/Data_Object.ipp CHANGED
@@ -6,9 +6,18 @@ 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 constexpr (std::is_pointer_v<T>)
10
+ {
11
+ return Exception(rb_eTypeError, "Wrong argument type. Expected: %s. Received: %s.",
12
+ detail::protect(rb_class2name, Data_Type<Pointer<std::remove_cv_t<std::remove_pointer_t<T>>>>::klass().value()),
13
+ detail::protect(rb_obj_classname, value));
14
+ }
15
+ else
16
+ {
17
+ return Exception(rb_eTypeError, "Wrong argument type. Expected: %s. Received: %s.",
18
+ detail::protect(rb_class2name, Data_Type<detail::intrinsic_type<T>>::klass().value()),
19
+ detail::protect(rb_obj_classname, value));
20
+ }
12
21
  }
13
22
 
14
23
  template<typename T>
@@ -102,6 +111,12 @@ namespace Rice::detail
102
111
  "Please include rice/stl.hpp header for STL support");
103
112
 
104
113
  public:
114
+ To_Ruby() = default;
115
+
116
+ explicit To_Ruby(Arg* arg) : arg_(arg)
117
+ {
118
+ }
119
+
105
120
  template<typename U>
106
121
  VALUE convert(U& data)
107
122
  {
@@ -123,6 +138,9 @@ namespace Rice::detail
123
138
  // matched <typename T> thus we have to tell wrap to copy the reference we are sending to it
124
139
  return detail::wrap(rubyTypeInfo.first, rubyTypeInfo.second, data, true);
125
140
  }
141
+
142
+ private:
143
+ Arg* arg_ = nullptr;
126
144
  };
127
145
 
128
146
  template <typename T>
@@ -141,7 +159,7 @@ namespace Rice::detail
141
159
  public:
142
160
  To_Ruby() = default;
143
161
 
144
- explicit To_Ruby(Return * returnInfo) : returnInfo_(returnInfo)
162
+ explicit To_Ruby(Arg* arg) : arg_(arg)
145
163
  {
146
164
  }
147
165
 
@@ -152,19 +170,45 @@ namespace Rice::detail
152
170
  // child class. Lookup the correct type so we return an instance of the correct Ruby class
153
171
  std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType<T>(data);
154
172
 
155
- bool isOwner = (this->returnInfo_ && this->returnInfo_->isOwner());
173
+ bool isOwner = (this->arg_ && this->arg_->isOwner());
156
174
  return detail::wrap(rubyTypeInfo.first, rubyTypeInfo.second, data, isOwner);
157
175
  }
158
176
  private:
159
- Return* returnInfo_ = nullptr;
177
+ Arg* arg_ = nullptr;
178
+ };
179
+
180
+ template <typename T, int N>
181
+ class To_Ruby<T[N]>
182
+ {
183
+ static_assert(!std::is_same_v<T, std::map<T, T>> && !std::is_same_v<T, std::unordered_map<T, T>> &&
184
+ !std::is_same_v<T, std::monostate> && !std::is_same_v<T, std::multimap<T, T>> &&
185
+ !std::is_same_v<T, std::optional<T>> && !std::is_same_v<T, std::pair<T, T>> &&
186
+ !std::is_same_v<T, std::set<T>> && !std::is_same_v<T, std::string> &&
187
+ !std::is_same_v<T, std::vector<T>>,
188
+ "Please include rice/stl.hpp header for STL support");
189
+
190
+ public:
191
+ To_Ruby() = default;
192
+
193
+ explicit To_Ruby(Arg* arg) : arg_(arg)
194
+ {
195
+ }
196
+
197
+ template<typename U>
198
+ VALUE convert(U data[N])
199
+ {
200
+ Buffer<T> buffer(data, N);
201
+ Data_Object<Buffer<T>> dataObject(std::move(buffer));
202
+ return dataObject.value();
203
+ }
204
+
205
+ private:
206
+ Arg* arg_ = nullptr;
160
207
  };
161
208
 
162
209
  template <typename T>
163
210
  class To_Ruby<T*>
164
211
  {
165
- static_assert(!std::is_fundamental_v<intrinsic_type<T>>,
166
- "Data_Object cannot be used with fundamental types");
167
-
168
212
  static_assert(!std::is_same_v<T, std::map<T, T>> && !std::is_same_v<T, std::unordered_map<T, T>> &&
169
213
  !std::is_same_v<T, std::monostate> && !std::is_same_v<T, std::multimap<T, T>> &&
170
214
  !std::is_same_v<T, std::optional<T>> && !std::is_same_v<T, std::pair<T, T>> &&
@@ -175,25 +219,24 @@ namespace Rice::detail
175
219
  public:
176
220
  To_Ruby() = default;
177
221
 
178
- explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
222
+ explicit To_Ruby(Arg* arg) : arg_(arg)
179
223
  {
180
224
  }
181
225
 
182
226
  template<typename U>
183
227
  VALUE convert(U* data)
184
228
  {
185
- bool isOwner = this->returnInfo_ && this->returnInfo_->isOwner();
229
+ bool isOwner = this->arg_ && this->arg_->isOwner();
230
+ bool isBuffer = this->arg_ && this->arg_->isBuffer();
186
231
 
187
232
  if (data == nullptr)
188
233
  {
189
234
  return Qnil;
190
235
  }
191
- else if (this->returnInfo_ && this->returnInfo_->isArray())
236
+ else if (std::is_fundamental_v<std::remove_pointer_t<T>> || isBuffer)
192
237
  {
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);
238
+ using Pointer_T = Pointer<remove_cv_recursive_t<U>>;
239
+ return detail::wrap(Data_Type<Pointer_T>::klass(), Data_Type<Pointer_T>::ruby_data_type(), data, isOwner);
197
240
  }
198
241
  else
199
242
  {
@@ -205,15 +248,12 @@ namespace Rice::detail
205
248
  }
206
249
 
207
250
  private:
208
- Return* returnInfo_ = nullptr;
251
+ Arg* arg_ = nullptr;
209
252
  };
210
253
 
211
254
  template <typename T>
212
- class To_Ruby<T*&>
255
+ class To_Ruby<T*&>
213
256
  {
214
- static_assert(!std::is_fundamental_v<intrinsic_type<T>>,
215
- "Data_Object cannot be used with fundamental types");
216
-
217
257
  static_assert(!std::is_same_v<T, std::map<T, T>> && !std::is_same_v<T, std::unordered_map<T, T>> &&
218
258
  !std::is_same_v<T, std::monostate> && !std::is_same_v<T, std::multimap<T, T>> &&
219
259
  !std::is_same_v<T, std::optional<T>> && !std::is_same_v<T, std::pair<T, T>> &&
@@ -224,25 +264,29 @@ namespace Rice::detail
224
264
  public:
225
265
  To_Ruby() = default;
226
266
 
227
- explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
267
+ explicit To_Ruby(Arg* arg) : arg_(arg)
228
268
  {
229
269
  }
230
270
 
231
271
  template<typename U>
232
272
  VALUE convert(U* data)
233
273
  {
234
- bool isOwner = this->returnInfo_ && this->returnInfo_->isOwner();
235
-
274
+ bool isOwner = this->arg_ && this->arg_->isOwner();
275
+ bool isBuffer = this->arg_ && this->arg_->isBuffer();
276
+
236
277
  if (data == nullptr)
237
278
  {
238
279
  return Qnil;
239
280
  }
240
- else if (this->returnInfo_ && this->returnInfo_->isArray())
281
+ else if constexpr (std::is_const_v<U>)
241
282
  {
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);
283
+ std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType(*data);
284
+ return detail::wrap(rubyTypeInfo.first, rubyTypeInfo.second, data, isOwner);
285
+ }
286
+ else if (std::is_fundamental_v<T> || isBuffer)
287
+ {
288
+ using Pointer_T = Pointer<remove_cv_recursive_t<U>>;
289
+ return detail::wrap(Data_Type<Pointer_T>::klass(), Data_Type<Pointer_T>::ruby_data_type(), data, isOwner);
246
290
  }
247
291
  else
248
292
  {
@@ -254,26 +298,16 @@ namespace Rice::detail
254
298
  }
255
299
 
256
300
  private:
257
- Return* returnInfo_ = nullptr;
301
+ Arg* arg_ = nullptr;
258
302
  };
259
303
 
260
304
  template <typename T>
261
305
  class To_Ruby<T**>
262
306
  {
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
307
  public:
274
308
  To_Ruby() = default;
275
309
 
276
- explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
310
+ explicit To_Ruby(Arg* arg) : arg_(arg)
277
311
  {
278
312
  }
279
313
 
@@ -282,11 +316,9 @@ namespace Rice::detail
282
316
  {
283
317
  if (data)
284
318
  {
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);
319
+ bool isOwner = this->arg_ && this->arg_->isOwner();
320
+ using Pointer_T = Pointer<remove_cv_recursive_t<U>*>;
321
+ return detail::wrap(Data_Type<Pointer_T>::klass(), Data_Type<Pointer_T>::ruby_data_type(), data, isOwner);
290
322
  }
291
323
  else
292
324
  {
@@ -295,7 +327,7 @@ namespace Rice::detail
295
327
  }
296
328
 
297
329
  private:
298
- Return* returnInfo_ = nullptr;
330
+ Arg* arg_ = nullptr;
299
331
  };
300
332
 
301
333
  template<typename T>
@@ -448,13 +480,9 @@ namespace Rice::detail
448
480
 
449
481
  // 99% of the time a T* represents a wrapped C++ object that we want to call methods on. However, T*
450
482
  // 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
483
  template<typename T>
453
484
  class From_Ruby<T*>
454
485
  {
455
- static_assert(!std::is_fundamental_v<intrinsic_type<T>>,
456
- "Data_Object cannot be used with fundamental types");
457
-
458
486
  static_assert(!std::is_same_v<T, std::map<T, T>> && !std::is_same_v<T, std::unordered_map<T, T>> &&
459
487
  !std::is_same_v<T, std::monostate> && !std::is_same_v<T, std::multimap<T, T>> &&
460
488
  !std::is_same_v<T, std::optional<T>> && !std::is_same_v<T, std::pair<T, T>> &&
@@ -475,22 +503,19 @@ namespace Rice::detail
475
503
  {
476
504
  switch (rb_type(value))
477
505
  {
506
+ case RUBY_T_NIL:
507
+ return Convertible::Exact;
508
+ break;
478
509
  case RUBY_T_DATA:
479
- if (this->arg_ && this->arg_->isArray())
510
+ if (Data_Type<T>::is_descendant(value))
480
511
  {
481
- return Data_Type<Buffer<T>>::is_descendant(value) ? Convertible::Exact : Convertible::None;
512
+ return Convertible::Exact;
482
513
  }
483
- else
514
+ else if (Data_Type<Pointer<T>>::is_descendant(value))
484
515
  {
485
- return Data_Type<T>::is_descendant(value) ? Convertible::Exact : Convertible::None;
516
+ return Convertible::Exact;
486
517
  }
487
- break;
488
- case RUBY_T_NIL:
489
- return Convertible::Exact;
490
- break;
491
- case RUBY_T_ARRAY:
492
- return Convertible::Exact;
493
- break;
518
+ [[fallthrough]];
494
519
  default:
495
520
  return Convertible::None;
496
521
  }
@@ -498,6 +523,8 @@ namespace Rice::detail
498
523
 
499
524
  T* convert(VALUE value)
500
525
  {
526
+ bool isOwner = this->arg_ && this->arg_->isOwner();
527
+
501
528
  switch (rb_type(value))
502
529
  {
503
530
  case RUBY_T_NIL:
@@ -507,20 +534,19 @@ namespace Rice::detail
507
534
  }
508
535
  case RUBY_T_DATA:
509
536
  {
510
- if (this->arg_ && this->arg_->isArray())
537
+ if (Data_Type<T>::is_descendant(value))
511
538
  {
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();
539
+ return detail::unwrap<Intrinsic_T>(value, Data_Type<Intrinsic_T>::ruby_data_type(), isOwner);
515
540
  }
516
- else
541
+ else if (Data_Type<Pointer<T>>::is_descendant(value))
517
542
  {
518
- return detail::unwrap<Intrinsic_T>(value, Data_Type<Intrinsic_T>::ruby_data_type(), this->arg_ && this->arg_->isOwner());
543
+ return detail::unwrap<T>(value, Data_Type<Pointer<T>>::ruby_data_type(), isOwner);
519
544
  }
545
+ [[fallthrough]];
520
546
  }
521
547
  default:
522
548
  {
523
- throw create_type_exception<Intrinsic_T>(value);
549
+ throw create_type_exception<T*>(value);
524
550
  }
525
551
  }
526
552
  }
@@ -532,9 +558,6 @@ namespace Rice::detail
532
558
  template<typename T>
533
559
  class From_Ruby<T*&>
534
560
  {
535
- static_assert(!std::is_fundamental_v<intrinsic_type<T>>,
536
- "Data_Object cannot be used with fundamental types");
537
-
538
561
  static_assert(!std::is_same_v<T, std::map<T, T>> && !std::is_same_v<T, std::unordered_map<T, T>> &&
539
562
  !std::is_same_v<T, std::monostate> && !std::is_same_v<T, std::multimap<T, T>> &&
540
563
  !std::is_same_v<T, std::optional<T>> && !std::is_same_v<T, std::pair<T, T>> &&
@@ -582,9 +605,6 @@ namespace Rice::detail
582
605
  template<typename T>
583
606
  class From_Ruby<T**>
584
607
  {
585
- static_assert(!std::is_fundamental_v<intrinsic_type<T>>,
586
- "Data_Object cannot be used with fundamental types");
587
-
588
608
  static_assert(!std::is_same_v<T, std::map<T, T>> && !std::is_same_v<T, std::unordered_map<T, T>> &&
589
609
  !std::is_same_v<T, std::monostate> && !std::is_same_v<T, std::multimap<T, T>> &&
590
610
  !std::is_same_v<T, std::optional<T>> && !std::is_same_v<T, std::pair<T, T>> &&
@@ -605,14 +625,11 @@ namespace Rice::detail
605
625
  switch (rb_type(value))
606
626
  {
607
627
  case RUBY_T_DATA:
608
- return Data_Type<Buffer<T*>>::is_descendant(value) ? Convertible::Exact : Convertible::None;
628
+ return Data_Type<Pointer<T*>>::is_descendant(value) ? Convertible::Exact : Convertible::None;
609
629
  break;
610
630
  case RUBY_T_NIL:
611
631
  return Convertible::Exact;
612
632
  break;
613
- case RUBY_T_ARRAY:
614
- return Convertible::Exact;
615
- break;
616
633
  default:
617
634
  return Convertible::None;
618
635
  }
@@ -620,12 +637,14 @@ namespace Rice::detail
620
637
 
621
638
  T** convert(VALUE value)
622
639
  {
640
+ bool isOwner = this->arg_ && this->arg_->isOwner();
641
+
623
642
  switch (rb_type(value))
624
643
  {
625
644
  case RUBY_T_DATA:
626
645
  {
627
- Buffer<Intrinsic_T*>* buffer = detail::unwrap<Buffer<Intrinsic_T*>>(value, Data_Type<Buffer<Intrinsic_T*>>::ruby_data_type(), false);
628
- return buffer->ptr();
646
+ T** result = detail::unwrap<Intrinsic_T*>(value, Data_Type<Pointer<T*>>::ruby_data_type(), isOwner);
647
+ return result;
629
648
  break;
630
649
  }
631
650
  case RUBY_T_NIL:
@@ -635,7 +654,7 @@ namespace Rice::detail
635
654
  }
636
655
  default:
637
656
  {
638
- throw create_type_exception<Intrinsic_T>(value);
657
+ throw create_type_exception<T**>(value);
639
658
  }
640
659
  }
641
660
  }
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
  }
data/rice/Enum.ipp CHANGED
@@ -49,8 +49,8 @@ namespace Rice
49
49
  Enum_T otherEnum = (Enum_T)other;
50
50
 
51
51
  Array result;
52
- result.push(self);
53
- result.push(otherEnum);
52
+ result.push(self, false);
53
+ result.push(otherEnum, true);
54
54
  return result;
55
55
  })
56
56
  .define_method("inspect", [](Enum_T& self)
@@ -95,25 +95,19 @@ namespace Rice
95
95
  }
96
96
  });
97
97
 
98
- // Add enumerable support
99
- klass.include_module(rb_mEnumerable)
100
- .define_singleton_method("each", [](VALUE ruby_klass) -> VALUE
101
- {
102
- if (!rb_block_given_p())
103
- {
104
- return rb_enumeratorize_with_size(ruby_klass, Identifier("each").to_sym(),
105
- 0, nullptr, 0);
106
- }
107
-
108
- for (auto& pair : valuesToNames_)
109
- {
110
- Enum_T enumValue = pair.first;
111
- VALUE value = detail::To_Ruby<Enum_T>().convert(enumValue);
112
- detail::protect(rb_yield, value);
113
- }
114
-
115
- return ruby_klass;
116
- }, Return().setValue());
98
+ // Add ability to get enum values
99
+ klass.define_singleton_method("values", [](VALUE ruby_klass) -> VALUE
100
+ {
101
+ Array result;
102
+
103
+ for (auto& pair : valuesToNames_)
104
+ {
105
+ Object enumValue = Class(ruby_klass).const_get(pair.second);
106
+ result.push(enumValue, false);
107
+ }
108
+
109
+ return result;
110
+ }, Return().setValue());
117
111
 
118
112
  // Add bitwise operators
119
113
  klass.define_method("&", [](Enum_T& self, Enum_T& other) -> Underlying_T
data/rice/Function.hpp ADDED
@@ -0,0 +1,17 @@
1
+ #ifndef Rice__Function__hpp_
2
+ #define Rice__Function__hpp_
3
+
4
+ namespace Rice
5
+ {
6
+ class Function
7
+ {
8
+ public:
9
+ Function& setNoGvl();
10
+ bool isNoGvl() const;
11
+
12
+ private:
13
+ bool isNoGvl_ = false;
14
+ };
15
+ } // Rice
16
+
17
+ #endif // Rice__Function__hpp_
data/rice/Function.ipp ADDED
@@ -0,0 +1,13 @@
1
+ namespace Rice
2
+ {
3
+ inline Function& Function::setNoGvl()
4
+ {
5
+ this->isNoGvl_ = true;
6
+ return *this;
7
+ }
8
+
9
+ inline bool Function::isNoGvl() const
10
+ {
11
+ return this->isNoGvl_;
12
+ }
13
+ } // Rice
data/rice/Pointer.hpp ADDED
@@ -0,0 +1,15 @@
1
+ #ifndef Rice__Pointer__hpp_
2
+ #define Rice__Pointer__hpp_
3
+
4
+ namespace Rice
5
+ {
6
+ template<typename T>
7
+ class Pointer
8
+ {
9
+ };
10
+
11
+ template<typename T>
12
+ Data_Type<Pointer<T>> define_pointer(std::string klassName = "");
13
+ }
14
+
15
+ #endif // Rice__Pointer__hpp_