rice 4.5.0 → 4.6.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 (166) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +23 -0
  3. data/CMakeLists.txt +31 -0
  4. data/CMakePresets.json +75 -0
  5. data/COPYING +3 -2
  6. data/FindRuby.cmake +437 -0
  7. data/Rakefile +5 -4
  8. data/include/rice/rice.hpp +5436 -3201
  9. data/include/rice/stl.hpp +2355 -1269
  10. data/lib/make_rice_headers.rb +79 -0
  11. data/lib/mkmf-rice.rb +4 -0
  12. data/lib/rice/version.rb +3 -0
  13. data/lib/rice.rb +1 -0
  14. data/lib/rubygems/builder.rb +11 -0
  15. data/lib/rubygems/cmake_builder.rb +113 -0
  16. data/lib/rubygems_plugin.rb +9 -0
  17. data/rice/Arg.hpp +7 -1
  18. data/rice/Arg.ipp +11 -2
  19. data/rice/Buffer.hpp +123 -0
  20. data/rice/Buffer.ipp +599 -0
  21. data/rice/Constructor.ipp +3 -3
  22. data/rice/Data_Object.hpp +2 -3
  23. data/rice/Data_Object.ipp +188 -188
  24. data/rice/Data_Type.hpp +4 -5
  25. data/rice/Data_Type.ipp +42 -26
  26. data/rice/Enum.hpp +0 -1
  27. data/rice/Enum.ipp +26 -23
  28. data/rice/Init.hpp +8 -0
  29. data/rice/Init.ipp +8 -0
  30. data/rice/MemoryView.ipp +1 -41
  31. data/rice/Return.hpp +1 -1
  32. data/rice/Return.ipp +6 -0
  33. data/rice/cpp_api/Array.hpp +209 -0
  34. data/rice/cpp_api/Array.ipp +304 -0
  35. data/rice/cpp_api/Builtin_Object.hpp +31 -0
  36. data/rice/cpp_api/Builtin_Object.ipp +37 -0
  37. data/rice/cpp_api/Class.hpp +70 -0
  38. data/rice/cpp_api/Class.ipp +97 -0
  39. data/rice/cpp_api/Encoding.hpp +32 -0
  40. data/rice/cpp_api/Encoding.ipp +59 -0
  41. data/rice/cpp_api/Hash.hpp +194 -0
  42. data/rice/cpp_api/Hash.ipp +257 -0
  43. data/rice/cpp_api/Identifier.hpp +46 -0
  44. data/rice/cpp_api/Identifier.ipp +31 -0
  45. data/rice/cpp_api/Module.hpp +72 -0
  46. data/rice/cpp_api/Module.ipp +101 -0
  47. data/rice/cpp_api/Object.hpp +272 -0
  48. data/rice/cpp_api/Object.ipp +235 -0
  49. data/rice/cpp_api/String.hpp +74 -0
  50. data/rice/cpp_api/String.ipp +120 -0
  51. data/rice/cpp_api/Struct.hpp +113 -0
  52. data/rice/cpp_api/Struct.ipp +92 -0
  53. data/rice/cpp_api/Symbol.hpp +46 -0
  54. data/rice/cpp_api/Symbol.ipp +93 -0
  55. data/rice/cpp_api/shared_methods.hpp +134 -0
  56. data/rice/detail/MethodInfo.hpp +1 -9
  57. data/rice/detail/MethodInfo.ipp +5 -72
  58. data/rice/detail/Native.hpp +3 -2
  59. data/rice/detail/Native.ipp +32 -4
  60. data/rice/detail/NativeAttributeGet.hpp +3 -2
  61. data/rice/detail/NativeAttributeGet.ipp +8 -2
  62. data/rice/detail/NativeAttributeSet.hpp +3 -2
  63. data/rice/detail/NativeAttributeSet.ipp +8 -2
  64. data/rice/detail/NativeCallbackFFI.ipp +1 -1
  65. data/rice/detail/NativeFunction.hpp +17 -6
  66. data/rice/detail/NativeFunction.ipp +168 -64
  67. data/rice/detail/NativeIterator.hpp +3 -2
  68. data/rice/detail/NativeIterator.ipp +8 -2
  69. data/rice/detail/RubyType.hpp +2 -5
  70. data/rice/detail/RubyType.ipp +50 -5
  71. data/rice/detail/Type.hpp +3 -1
  72. data/rice/detail/Type.ipp +61 -31
  73. data/rice/detail/Wrapper.hpp +68 -33
  74. data/rice/detail/Wrapper.ipp +103 -113
  75. data/rice/detail/from_ruby.hpp +5 -4
  76. data/rice/detail/from_ruby.ipp +737 -365
  77. data/rice/detail/to_ruby.ipp +1092 -186
  78. data/rice/global_function.ipp +1 -1
  79. data/rice/libc/file.hpp +11 -0
  80. data/rice/libc/file.ipp +32 -0
  81. data/rice/rice.hpp +23 -16
  82. data/rice/stl/complex.hpp +6 -0
  83. data/rice/stl/complex.ipp +93 -0
  84. data/rice/stl/exception.hpp +11 -0
  85. data/rice/stl/exception.ipp +29 -0
  86. data/rice/stl/exception_ptr.hpp +6 -0
  87. data/rice/stl/exception_ptr.ipp +27 -0
  88. data/rice/stl/map.hpp +12 -0
  89. data/rice/stl/map.ipp +469 -0
  90. data/rice/stl/monostate.hpp +6 -0
  91. data/rice/stl/monostate.ipp +80 -0
  92. data/rice/stl/multimap.hpp +14 -0
  93. data/rice/stl/multimap.ipp +448 -0
  94. data/rice/stl/optional.hpp +6 -0
  95. data/rice/stl/optional.ipp +118 -0
  96. data/rice/stl/pair.hpp +13 -0
  97. data/rice/stl/pair.ipp +155 -0
  98. data/rice/stl/reference_wrapper.hpp +6 -0
  99. data/rice/stl/reference_wrapper.ipp +41 -0
  100. data/rice/stl/set.hpp +12 -0
  101. data/rice/stl/set.ipp +495 -0
  102. data/rice/stl/shared_ptr.hpp +28 -0
  103. data/rice/stl/shared_ptr.ipp +224 -0
  104. data/rice/stl/string.hpp +6 -0
  105. data/rice/stl/string.ipp +158 -0
  106. data/rice/stl/string_view.hpp +6 -0
  107. data/rice/stl/string_view.ipp +65 -0
  108. data/rice/stl/tuple.hpp +6 -0
  109. data/rice/stl/tuple.ipp +128 -0
  110. data/rice/stl/type_index.hpp +6 -0
  111. data/rice/stl/type_index.ipp +30 -0
  112. data/rice/stl/type_info.hpp +6 -0
  113. data/rice/stl/type_info.ipp +29 -0
  114. data/rice/stl/unique_ptr.hpp +22 -0
  115. data/rice/stl/unique_ptr.ipp +139 -0
  116. data/rice/stl/unordered_map.hpp +12 -0
  117. data/rice/stl/unordered_map.ipp +469 -0
  118. data/rice/stl/variant.hpp +6 -0
  119. data/rice/stl/variant.ipp +242 -0
  120. data/rice/stl/vector.hpp +12 -0
  121. data/rice/stl/vector.ipp +590 -0
  122. data/rice/stl.hpp +7 -3
  123. data/rice/traits/attribute_traits.hpp +26 -0
  124. data/rice/traits/function_traits.hpp +95 -0
  125. data/rice/traits/method_traits.hpp +47 -0
  126. data/rice/traits/rice_traits.hpp +160 -0
  127. data/rice.gemspec +85 -0
  128. data/test/embed_ruby.cpp +3 -0
  129. data/test/ruby/test_multiple_extensions_same_class.rb +14 -14
  130. data/test/test_Array.cpp +6 -3
  131. data/test/test_Attribute.cpp +34 -1
  132. data/test/test_Buffer.cpp +285 -0
  133. data/test/test_Callback.cpp +2 -3
  134. data/test/test_Data_Object.cpp +88 -34
  135. data/test/test_Data_Type.cpp +106 -65
  136. data/test/test_Director.cpp +7 -3
  137. data/test/test_Enum.cpp +5 -2
  138. data/test/test_File.cpp +1 -1
  139. data/test/test_From_Ruby.cpp +181 -114
  140. data/test/test_Iterator.cpp +1 -1
  141. data/test/{test_JumpException.cpp → test_Jump_Exception.cpp} +1 -0
  142. data/test/test_Keep_Alive.cpp +7 -18
  143. data/test/test_Keep_Alive_No_Wrapper.cpp +0 -1
  144. data/test/test_Module.cpp +13 -6
  145. data/test/test_Native_Registry.cpp +0 -1
  146. data/test/test_Overloads.cpp +180 -5
  147. data/test/test_Ownership.cpp +100 -57
  148. data/test/test_Proc.cpp +0 -1
  149. data/test/test_Self.cpp +4 -4
  150. data/test/test_Stl_Map.cpp +37 -39
  151. data/test/test_Stl_Multimap.cpp +693 -0
  152. data/test/test_Stl_Pair.cpp +8 -8
  153. data/test/test_Stl_Reference_Wrapper.cpp +4 -2
  154. data/test/test_Stl_Set.cpp +790 -0
  155. data/test/{test_Stl_SmartPointer.cpp → test_Stl_SharedPtr.cpp} +97 -127
  156. data/test/test_Stl_Tuple.cpp +116 -0
  157. data/test/test_Stl_Type.cpp +1 -1
  158. data/test/test_Stl_UniquePtr.cpp +202 -0
  159. data/test/test_Stl_Unordered_Map.cpp +28 -34
  160. data/test/test_Stl_Variant.cpp +217 -89
  161. data/test/test_Stl_Vector.cpp +209 -83
  162. data/test/test_To_Ruby.cpp +373 -1
  163. data/test/test_Type.cpp +85 -14
  164. data/test/test_global_functions.cpp +17 -4
  165. metadata +94 -10
  166. data/rice/detail/TupleIterator.hpp +0 -14
@@ -42,7 +42,7 @@ namespace Rice::detail
42
42
  }
43
43
  else if (RubyType_T::Narrowable.find(valueType) != RubyType_T::Narrowable.end())
44
44
  {
45
- return Convertible::Narrowable;
45
+ return Convertible::Narrow;
46
46
  }
47
47
  else
48
48
  {
@@ -60,73 +60,117 @@ namespace Rice::detail
60
60
  class FromRubyFundamental<T*>
61
61
  {
62
62
  public:
63
- using RubyType_T = RubyType<T>;
64
-
65
63
  static Convertible is_convertible(VALUE value)
66
64
  {
67
65
  ruby_value_type valueType = rb_type(value);
68
66
 
69
- if (RubyType_T::Exact.find(valueType) != RubyType_T::Exact.end())
70
- {
71
- return Convertible::Exact;
72
- }
73
- else if (valueType == RUBY_T_ARRAY)
74
- {
75
- return Convertible::Exact;
76
- }
77
- else if (valueType == RUBY_T_STRING)
67
+ switch (valueType)
78
68
  {
79
- // Maybe we should check for ascii8bit encoding?
80
- //if (RB_ENCODING_IS_ASCII8BIT(value))
81
- return Convertible::Exact;
69
+ case RUBY_T_NIL:
70
+ {
71
+ return Convertible::Exact;
72
+ break;
73
+ }
74
+ case RUBY_T_DATA:
75
+ {
76
+ return Data_Type<Buffer<T>>::is_descendant(value) ? Convertible::Exact : Convertible::None;
77
+ }
78
+ default:
79
+ {
80
+ return Convertible::None;
81
+ }
82
82
  }
83
-
84
- return Convertible::None;
85
83
  }
86
84
 
87
- static std::unique_ptr<T[]> convert(VALUE value)
85
+ static T* convert(VALUE value, Arg* arg)
88
86
  {
89
87
  ruby_value_type valueType = rb_type(value);
88
+
90
89
  switch (valueType)
91
90
  {
92
91
  case RUBY_T_NIL:
93
92
  {
94
93
  return nullptr;
95
- break;
96
94
  }
97
- case RUBY_T_ARRAY:
95
+ case RUBY_T_DATA:
98
96
  {
99
- Array array(value);
100
- return array.pack<T>();
101
- break;
97
+ if (Data_Type<Buffer<T>>::is_descendant(value))
98
+ {
99
+ Buffer<T>* buffer = unwrap<Buffer<T>>(value, Data_Type<Buffer<T>>::ruby_data_type(), false);
100
+ if (arg && arg->isOwner())
101
+ {
102
+ buffer->release();
103
+ }
104
+ return buffer->ptr();
105
+ }
106
+ [[fallthrough]];
102
107
  }
103
- case RUBY_T_STRING:
108
+ default:
104
109
  {
105
- long size = RSTRING_LEN(value);
106
- // Add null character to end
107
- std::unique_ptr<T[]> dest = std::make_unique<T[]>(size + 1);
108
- dest.get()[size] = 0;
109
- memcpy(dest.get(), RSTRING_PTR(value), size);
110
+ std::string name = typeName(typeid(Buffer<intrinsic_type<T>>));
111
+ std::string expected = rubyClassName(name);
112
+ throw Exception(rb_eTypeError, "wrong argument type %s (expected % s)",
113
+ detail::protect(rb_obj_classname, value), expected.c_str());
114
+ }
115
+ }
116
+ }
117
+ };
110
118
 
111
- return std::move(dest);
119
+ template<typename T>
120
+ class FromRubyFundamental<T**>
121
+ {
122
+ public:
123
+ static Convertible is_convertible(VALUE value)
124
+ {
125
+ ruby_value_type valueType = rb_type(value);
126
+
127
+ switch (valueType)
128
+ {
129
+ case RUBY_T_NIL:
130
+ {
131
+ return Convertible::Exact;
112
132
  break;
113
133
  }
134
+ case RUBY_T_DATA:
135
+ {
136
+ return Data_Type<Buffer<T*>>::is_descendant(value) ? Convertible::Exact : Convertible::None;
137
+ }
114
138
  default:
115
139
  {
116
- if (RubyType_T::Exact.find(valueType) != RubyType_T::Exact.end() ||
117
- RubyType_T::Castable.find(valueType) != RubyType_T::Castable.end() ||
118
- RubyType_T::Narrowable.find(valueType) != RubyType_T::Narrowable.end())
119
- {
120
- std::unique_ptr<T[]> dest = std::make_unique<T[]>(1);
121
- *(dest.get()) = (T)protect(RubyType_T::fromRuby, value);
122
- return std::move(dest);
123
- }
124
- else
140
+ return Convertible::None;
141
+ }
142
+ }
143
+ }
144
+
145
+ static T** convert(VALUE value, Arg* arg)
146
+ {
147
+ ruby_value_type valueType = rb_type(value);
148
+
149
+ switch (valueType)
150
+ {
151
+ case RUBY_T_NIL:
152
+ {
153
+ return nullptr;
154
+ }
155
+ case RUBY_T_DATA:
156
+ {
157
+ if (Data_Type<Buffer<T*>>::is_descendant(value))
125
158
  {
126
- std::string typeName = detail::typeName(typeid(T));
127
- throw Exception(rb_eTypeError, "wrong argument type %s (expected % s*)",
128
- detail::protect(rb_obj_classname, value), typeName.c_str());
159
+ Buffer<T*>* buffer = unwrap<Buffer<T*>>(value, Data_Type<Buffer<T*>>::ruby_data_type(), false);
160
+ if (arg && arg->isOwner())
161
+ {
162
+ buffer->release();
163
+ }
164
+ return buffer->ptr();
129
165
  }
166
+ [[fallthrough]];
167
+ }
168
+ default:
169
+ {
170
+ std::string name = typeName(typeid(Buffer<intrinsic_type<T>*>));
171
+ std::string expected = rubyClassName(name);
172
+ throw Exception(rb_eTypeError, "wrong argument type %s (expected % s)",
173
+ detail::protect(rb_obj_classname, value), expected.c_str());
130
174
  }
131
175
  }
132
176
  }
@@ -150,14 +194,7 @@ namespace Rice::detail
150
194
 
151
195
  bool convert(VALUE value)
152
196
  {
153
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
154
- {
155
- return this->arg_->defaultValue<bool>();
156
- }
157
- else
158
- {
159
- return FromRubyFundamental<bool>::convert(value);
160
- }
197
+ return FromRubyFundamental<bool>::convert(value);
161
198
  }
162
199
 
163
200
  private:
@@ -168,6 +205,8 @@ namespace Rice::detail
168
205
  class From_Ruby<bool&>
169
206
  {
170
207
  public:
208
+ using Buffer_T = Buffer<bool>;
209
+
171
210
  From_Ruby() = default;
172
211
 
173
212
  explicit From_Ruby(Arg* arg) : arg_(arg)
@@ -176,14 +215,22 @@ namespace Rice::detail
176
215
 
177
216
  Convertible is_convertible(VALUE value)
178
217
  {
179
- return FromRubyFundamental<bool>::is_convertible(value);
218
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
219
+ {
220
+ return Convertible::Exact;
221
+ }
222
+ else
223
+ {
224
+ return FromRubyFundamental<bool>::is_convertible(value);
225
+ }
180
226
  }
181
227
 
182
228
  bool& convert(VALUE value)
183
229
  {
184
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
230
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
185
231
  {
186
- return this->arg_->defaultValue<bool>();
232
+ Buffer_T* buffer = unwrap<Buffer_T>(value, Data_Type<Buffer_T>::ruby_data_type(), false);
233
+ return buffer->reference();
187
234
  }
188
235
  else
189
236
  {
@@ -207,18 +254,6 @@ namespace Rice::detail
207
254
  {
208
255
  }
209
256
 
210
- // Need move constructor and assignment due to std::unique_ptr
211
- From_Ruby(From_Ruby&& other) = default;
212
- From_Ruby& operator=(From_Ruby&& other) = default;
213
-
214
- ~From_Ruby()
215
- {
216
- if (this->arg_ && this->arg_->isOwner())
217
- {
218
- this->converted_.release();
219
- }
220
- }
221
-
222
257
  Convertible is_convertible(VALUE value)
223
258
  {
224
259
  return FromRubyFundamental<bool>::is_convertible(value);
@@ -226,13 +261,11 @@ namespace Rice::detail
226
261
 
227
262
  bool* convert(VALUE value)
228
263
  {
229
- this->converted_ = FromRubyFundamental<bool*>::convert(value);
230
- return this->converted_.get();
264
+ return FromRubyFundamental<bool*>::convert(value, this->arg_);
231
265
  }
232
266
 
233
267
  private:
234
268
  Arg* arg_ = nullptr;
235
- std::unique_ptr<bool[]> converted_;
236
269
  };
237
270
 
238
271
  // =========== char ============
@@ -253,14 +286,7 @@ namespace Rice::detail
253
286
 
254
287
  char convert(VALUE value)
255
288
  {
256
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
257
- {
258
- return this->arg_->defaultValue<char>();
259
- }
260
- else
261
- {
262
- return FromRubyFundamental<char>::convert(value);
263
- }
289
+ return FromRubyFundamental<char>::convert(value);
264
290
  }
265
291
 
266
292
  private:
@@ -271,6 +297,8 @@ namespace Rice::detail
271
297
  class From_Ruby<char&>
272
298
  {
273
299
  public:
300
+ using Buffer_T = Buffer<char>;
301
+
274
302
  From_Ruby() = default;
275
303
 
276
304
  explicit From_Ruby(Arg* arg) : arg_(arg)
@@ -279,14 +307,22 @@ namespace Rice::detail
279
307
 
280
308
  Convertible is_convertible(VALUE value)
281
309
  {
282
- return FromRubyFundamental<char>::is_convertible(value);
310
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
311
+ {
312
+ return Convertible::Exact;
313
+ }
314
+ else
315
+ {
316
+ return FromRubyFundamental<char>::is_convertible(value);
317
+ }
283
318
  }
284
319
 
285
320
  char& convert(VALUE value)
286
321
  {
287
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
322
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
288
323
  {
289
- return this->arg_->defaultValue<char>();
324
+ Buffer_T* buffer = unwrap<Buffer_T>(value, Data_Type<Buffer_T>::ruby_data_type(), false);
325
+ return buffer->reference();
290
326
  }
291
327
  else
292
328
  {
@@ -310,70 +346,82 @@ namespace Rice::detail
310
346
  {
311
347
  }
312
348
 
313
- // Need move constructor and assignment due to std::unique_ptr
314
- From_Ruby(From_Ruby&& other) = default;
315
- From_Ruby& operator=(From_Ruby&& other) = default;
316
-
317
- ~From_Ruby()
349
+ Convertible is_convertible(VALUE value)
318
350
  {
319
- if (this->arg_ && this->arg_->isOwner())
351
+ switch (rb_type(value))
320
352
  {
321
- this->converted_.release();
353
+ case RUBY_T_NIL:
354
+ {
355
+ return Convertible::Exact;
356
+ }
357
+ case RUBY_T_STRING:
358
+ {
359
+ return Convertible::Exact;
360
+ }
361
+ default:
362
+ {
363
+ return FromRubyFundamental<char*>::is_convertible(value);
364
+ }
322
365
  }
323
366
  }
324
367
 
325
- Convertible is_convertible(VALUE value)
326
- {
327
- return FromRubyFundamental<char*>::is_convertible(value);
328
- }
329
-
330
368
  char* convert(VALUE value)
331
369
  {
332
- this->converted_ = FromRubyFundamental<char*>::convert(value);
333
- return this->converted_.get();
370
+ switch (rb_type(value))
371
+ {
372
+ case RUBY_T_NIL:
373
+ {
374
+ return nullptr;
375
+ }
376
+ case RUBY_T_STRING:
377
+ {
378
+ // WARNING - this shares the Ruby string memory directly with C++. value really should be frozen.
379
+ // Maybe we should enforce that? Note the user can always create a Buffer to allocate new memory.
380
+ return rb_string_value_cstr(&value);
381
+ }
382
+ default:
383
+ {
384
+ char* rb_string_value_cstr(volatile VALUE * ptr);
385
+ return FromRubyFundamental<char*>::convert(value, this->arg_);
386
+ }
387
+ }
334
388
  }
335
389
 
336
390
  private:
337
391
  Arg* arg_ = nullptr;
338
- std::unique_ptr<char[]> converted_;
339
392
  };
340
393
 
341
394
  template<>
342
- class From_Ruby<const char*>
395
+ class From_Ruby<const char*> : public From_Ruby<char*>
396
+ {
397
+ };
398
+
399
+ template<>
400
+ class From_Ruby<char**>
343
401
  {
344
402
  public:
345
403
  From_Ruby() = default;
346
404
 
347
405
  explicit From_Ruby(Arg* arg) : arg_(arg)
348
- {
349
- }
350
-
351
- // Need move constructor and assignment due to std::unique_ptr
352
- From_Ruby(From_Ruby&& other) = default;
353
- From_Ruby& operator=(From_Ruby&& other) = default;
354
-
355
- ~From_Ruby()
356
406
  {
357
407
  if (this->arg_ && this->arg_->isOwner())
358
408
  {
359
- this->converted_.release();
409
+ throw std::runtime_error("Cannot transfer ownership of an array of pointers to a fundamental type");
360
410
  }
361
411
  }
362
412
 
363
413
  Convertible is_convertible(VALUE value)
364
414
  {
365
- return FromRubyFundamental<char*>::is_convertible(value);
415
+ return FromRubyFundamental<char**>::is_convertible(value);
366
416
  }
367
417
 
368
- char* convert(VALUE value)
418
+ char** convert(VALUE value)
369
419
  {
370
- this->converted_ = FromRubyFundamental<char*>::convert(value);
371
- return this->converted_.get();
420
+ return FromRubyFundamental<char**>::convert(value, this->arg_);
372
421
  }
373
422
 
374
423
  private:
375
424
  Arg* arg_ = nullptr;
376
- std::unique_ptr<char[]> converted_;
377
425
  };
378
426
 
379
427
  // =========== unsigned char ============
@@ -394,14 +442,7 @@ namespace Rice::detail
394
442
 
395
443
  unsigned char convert(VALUE value)
396
444
  {
397
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
398
- {
399
- return this->arg_->defaultValue<unsigned char>();
400
- }
401
- else
402
- {
403
- return FromRubyFundamental<unsigned char>::convert(value);
404
- }
445
+ return FromRubyFundamental<unsigned char>::convert(value);
405
446
  }
406
447
 
407
448
  private:
@@ -412,6 +453,8 @@ namespace Rice::detail
412
453
  class From_Ruby<unsigned char&>
413
454
  {
414
455
  public:
456
+ using Buffer_T = Buffer<unsigned char>;
457
+
415
458
  From_Ruby() = default;
416
459
 
417
460
  explicit From_Ruby(Arg* arg) : arg_(arg)
@@ -420,14 +463,22 @@ namespace Rice::detail
420
463
 
421
464
  Convertible is_convertible(VALUE value)
422
465
  {
423
- return FromRubyFundamental<unsigned char>::is_convertible(value);
466
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
467
+ {
468
+ return Convertible::Exact;
469
+ }
470
+ else
471
+ {
472
+ return FromRubyFundamental<unsigned char>::is_convertible(value);
473
+ }
424
474
  }
425
475
 
426
476
  unsigned char& convert(VALUE value)
427
477
  {
428
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
478
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
429
479
  {
430
- return this->arg_->defaultValue<unsigned char>();
480
+ Buffer_T* buffer = unwrap<Buffer_T>(value, Data_Type<Buffer_T>::ruby_data_type(), false);
481
+ return buffer->reference();
431
482
  }
432
483
  else
433
484
  {
@@ -451,32 +502,46 @@ namespace Rice::detail
451
502
  {
452
503
  }
453
504
 
454
- // Need move constructor and assignment due to std::unique_ptr
455
- From_Ruby(From_Ruby&& other) = default;
456
- From_Ruby& operator=(From_Ruby&& other) = default;
505
+ Convertible is_convertible(VALUE value)
506
+ {
507
+ return FromRubyFundamental<unsigned char*>::is_convertible(value);
508
+ }
457
509
 
458
- ~From_Ruby()
510
+ unsigned char* convert(VALUE value)
511
+ {
512
+ return FromRubyFundamental<unsigned char*>::convert(value, this->arg_);
513
+ }
514
+
515
+ private:
516
+ Arg* arg_ = nullptr;
517
+ };
518
+
519
+ template<>
520
+ class From_Ruby<unsigned char**>
521
+ {
522
+ public:
523
+ From_Ruby() = default;
524
+
525
+ explicit From_Ruby(Arg* arg) : arg_(arg)
459
526
  {
460
527
  if (this->arg_ && this->arg_->isOwner())
461
528
  {
462
- this->converted_.release();
529
+ throw std::runtime_error("Cannot transfer ownership of an array of pointers to a fundamental type");
463
530
  }
464
531
  }
465
532
 
466
533
  Convertible is_convertible(VALUE value)
467
534
  {
468
- return FromRubyFundamental<unsigned char*>::is_convertible(value);
535
+ return FromRubyFundamental<unsigned char**>::is_convertible(value);
469
536
  }
470
537
 
471
- unsigned char* convert(VALUE value)
538
+ unsigned char** convert(VALUE value)
472
539
  {
473
- this->converted_ = FromRubyFundamental<unsigned char*>::convert(value);
474
- return this->converted_.get();
540
+ return FromRubyFundamental<unsigned char**>::convert(value, this->arg_);
475
541
  }
476
542
 
477
543
  private:
478
544
  Arg* arg_ = nullptr;
479
- std::unique_ptr<unsigned char[]> converted_;
480
545
  };
481
546
 
482
547
  // =========== signed char ============
@@ -497,18 +562,54 @@ namespace Rice::detail
497
562
 
498
563
  signed char convert(VALUE value)
499
564
  {
500
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
565
+ return FromRubyFundamental<signed char>::convert(value);
566
+ }
567
+
568
+ private:
569
+ Arg* arg_ = nullptr;
570
+ };
571
+
572
+ template<>
573
+ class From_Ruby<signed char&>
574
+ {
575
+ public:
576
+ using Buffer_T = Buffer<signed char>;
577
+
578
+ From_Ruby() = default;
579
+
580
+ explicit From_Ruby(Arg* arg) : arg_(arg)
581
+ {
582
+ }
583
+
584
+ Convertible is_convertible(VALUE value)
585
+ {
586
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
501
587
  {
502
- return this->arg_->defaultValue<signed char>();
588
+ return Convertible::Exact;
503
589
  }
504
590
  else
505
591
  {
506
- return FromRubyFundamental<signed char>::convert(value);
592
+ return FromRubyFundamental<signed char>::is_convertible(value);
593
+ }
594
+ }
595
+
596
+ signed char& convert(VALUE value)
597
+ {
598
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
599
+ {
600
+ Buffer_T* buffer = unwrap<Buffer_T>(value, Data_Type<Buffer_T>::ruby_data_type(), false);
601
+ return buffer->reference();
602
+ }
603
+ else
604
+ {
605
+ this->converted_ = FromRubyFundamental<signed char>::convert(value);
606
+ return this->converted_;
507
607
  }
508
608
  }
509
609
 
510
610
  private:
511
611
  Arg* arg_ = nullptr;
612
+ signed char converted_ = 0;
512
613
  };
513
614
 
514
615
  template<>
@@ -521,32 +622,46 @@ namespace Rice::detail
521
622
  {
522
623
  }
523
624
 
524
- // Need move constructor and assignment due to std::unique_ptr
525
- From_Ruby(From_Ruby&& other) = default;
526
- From_Ruby& operator=(From_Ruby&& other) = default;
625
+ Convertible is_convertible(VALUE value)
626
+ {
627
+ return FromRubyFundamental<signed char*>::is_convertible(value);
628
+ }
629
+
630
+ signed char* convert(VALUE value)
631
+ {
632
+ return FromRubyFundamental<signed char*>::convert(value, this->arg_);
633
+ }
634
+
635
+ private:
636
+ Arg* arg_ = nullptr;
637
+ };
638
+
639
+ template<>
640
+ class From_Ruby<signed char**>
641
+ {
642
+ public:
643
+ From_Ruby() = default;
527
644
 
528
- ~From_Ruby()
645
+ explicit From_Ruby(Arg* arg) : arg_(arg)
529
646
  {
530
647
  if (this->arg_ && this->arg_->isOwner())
531
648
  {
532
- this->converted_.release();
649
+ throw std::runtime_error("Cannot transfer ownership of an array of pointers to a fundamental type");
533
650
  }
534
651
  }
535
652
 
536
653
  Convertible is_convertible(VALUE value)
537
654
  {
538
- return FromRubyFundamental<signed char*>::is_convertible(value);
655
+ return FromRubyFundamental<signed char**>::is_convertible(value);
539
656
  }
540
657
 
541
- signed char* convert(VALUE value)
658
+ signed char** convert(VALUE value)
542
659
  {
543
- this->converted_ = FromRubyFundamental<signed char*>::convert(value);
544
- return this->converted_.get();
660
+ return FromRubyFundamental<signed char**>::convert(value, this->arg_);
545
661
  }
546
662
 
547
663
  private:
548
664
  Arg* arg_ = nullptr;
549
- std::unique_ptr<signed char[]> converted_;
550
665
  };
551
666
 
552
667
  // =========== double ============
@@ -567,14 +682,7 @@ namespace Rice::detail
567
682
 
568
683
  double convert(VALUE value)
569
684
  {
570
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
571
- {
572
- return this->arg_->defaultValue<double>();
573
- }
574
- else
575
- {
576
- return FromRubyFundamental<double>::convert(value);
577
- }
685
+ return FromRubyFundamental<double>::convert(value);
578
686
  }
579
687
 
580
688
  private:
@@ -585,6 +693,8 @@ namespace Rice::detail
585
693
  class From_Ruby<double&>
586
694
  {
587
695
  public:
696
+ using Buffer_T = Buffer<double>;
697
+
588
698
  From_Ruby() = default;
589
699
 
590
700
  explicit From_Ruby(Arg* arg) : arg_(arg)
@@ -593,14 +703,22 @@ namespace Rice::detail
593
703
 
594
704
  Convertible is_convertible(VALUE value)
595
705
  {
596
- return FromRubyFundamental<double>::is_convertible(value);
706
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
707
+ {
708
+ return Convertible::Exact;
709
+ }
710
+ else
711
+ {
712
+ return FromRubyFundamental<double>::is_convertible(value);
713
+ }
597
714
  }
598
715
 
599
716
  double& convert(VALUE value)
600
717
  {
601
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
718
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
602
719
  {
603
- return this->arg_->defaultValue<double>();
720
+ Buffer_T* buffer = unwrap<Buffer_T>(value, Data_Type<Buffer_T>::ruby_data_type(), false);
721
+ return buffer->reference();
604
722
  }
605
723
  else
606
724
  {
@@ -624,32 +742,46 @@ namespace Rice::detail
624
742
  {
625
743
  }
626
744
 
627
- // Need move constructor and assignment due to std::unique_ptr
628
- From_Ruby(From_Ruby&& other) = default;
629
- From_Ruby& operator=(From_Ruby&& other) = default;
745
+ Convertible is_convertible(VALUE value)
746
+ {
747
+ return FromRubyFundamental<double*>::is_convertible(value);
748
+ }
630
749
 
631
- ~From_Ruby()
750
+ double* convert(VALUE value)
751
+ {
752
+ return FromRubyFundamental<double*>::convert(value, this->arg_);
753
+ }
754
+
755
+ private:
756
+ Arg* arg_ = nullptr;
757
+ };
758
+
759
+ template<>
760
+ class From_Ruby<double**>
761
+ {
762
+ public:
763
+ From_Ruby() = default;
764
+
765
+ explicit From_Ruby(Arg* arg) : arg_(arg)
632
766
  {
633
767
  if (this->arg_ && this->arg_->isOwner())
634
768
  {
635
- this->converted_.release();
769
+ throw std::runtime_error("Cannot transfer ownership of an array of pointers to a fundamental type");
636
770
  }
637
771
  }
638
772
 
639
773
  Convertible is_convertible(VALUE value)
640
774
  {
641
- return FromRubyFundamental<double*>::is_convertible(value);
775
+ return FromRubyFundamental<double**>::is_convertible(value);
642
776
  }
643
777
 
644
- double* convert(VALUE value)
778
+ double** convert(VALUE value)
645
779
  {
646
- this->converted_ = FromRubyFundamental<double*>::convert(value);
647
- return this->converted_.get();
780
+ return FromRubyFundamental<double**>::convert(value, this->arg_);
648
781
  }
649
782
 
650
783
  private:
651
784
  Arg* arg_ = nullptr;
652
- std::unique_ptr<double[]> converted_;
653
785
  };
654
786
 
655
787
  // =========== float ============
@@ -670,14 +802,7 @@ namespace Rice::detail
670
802
 
671
803
  float convert(VALUE value)
672
804
  {
673
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
674
- {
675
- return this->arg_->defaultValue<float>();
676
- }
677
- else
678
- {
679
- return FromRubyFundamental<float>::convert(value);
680
- }
805
+ return FromRubyFundamental<float>::convert(value);
681
806
  }
682
807
 
683
808
  private:
@@ -688,6 +813,8 @@ namespace Rice::detail
688
813
  class From_Ruby<float&>
689
814
  {
690
815
  public:
816
+ using Buffer_T = Buffer<float>;
817
+
691
818
  From_Ruby() = default;
692
819
 
693
820
  explicit From_Ruby(Arg* arg) : arg_(arg)
@@ -696,14 +823,22 @@ namespace Rice::detail
696
823
 
697
824
  Convertible is_convertible(VALUE value)
698
825
  {
699
- return FromRubyFundamental<float>::is_convertible(value);
826
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
827
+ {
828
+ return Convertible::Exact;
829
+ }
830
+ else
831
+ {
832
+ return FromRubyFundamental<float>::is_convertible(value);
833
+ }
700
834
  }
701
835
 
702
836
  float& convert(VALUE value)
703
837
  {
704
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
838
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
705
839
  {
706
- return this->arg_->defaultValue<float>();
840
+ Buffer_T* buffer = unwrap<Buffer_T>(value, Data_Type<Buffer_T>::ruby_data_type(), false);
841
+ return buffer->reference();
707
842
  }
708
843
  else
709
844
  {
@@ -727,32 +862,46 @@ namespace Rice::detail
727
862
  {
728
863
  }
729
864
 
730
- // Need move constructor and assignment due to std::unique_ptr
731
- From_Ruby(From_Ruby&& other) = default;
732
- From_Ruby& operator=(From_Ruby&& other) = default;
865
+ Convertible is_convertible(VALUE value)
866
+ {
867
+ return FromRubyFundamental<float*>::is_convertible(value);
868
+ }
869
+
870
+ float* convert(VALUE value)
871
+ {
872
+ return FromRubyFundamental<float*>::convert(value, this->arg_);
873
+ }
874
+
875
+ private:
876
+ Arg* arg_ = nullptr;
877
+ };
878
+
879
+ template<>
880
+ class From_Ruby<float**>
881
+ {
882
+ public:
883
+ From_Ruby() = default;
733
884
 
734
- ~From_Ruby()
885
+ explicit From_Ruby(Arg* arg) : arg_(arg)
735
886
  {
736
887
  if (this->arg_ && this->arg_->isOwner())
737
888
  {
738
- this->converted_.release();
889
+ throw std::runtime_error("Cannot transfer ownership of an array of pointers to a fundamental type");
739
890
  }
740
891
  }
741
892
 
742
893
  Convertible is_convertible(VALUE value)
743
894
  {
744
- return FromRubyFundamental<float*>::is_convertible(value);
895
+ return FromRubyFundamental<float**>::is_convertible(value);
745
896
  }
746
897
 
747
- float* convert(VALUE value)
898
+ float** convert(VALUE value)
748
899
  {
749
- this->converted_ = FromRubyFundamental<float*>::convert(value);
750
- return this->converted_.get();
900
+ return FromRubyFundamental<float**>::convert(value, this->arg_);
751
901
  }
752
902
 
753
903
  private:
754
904
  Arg* arg_ = nullptr;
755
- std::unique_ptr<float[]> converted_;
756
905
  };
757
906
 
758
907
  // =========== int ============
@@ -784,14 +933,7 @@ namespace Rice::detail
784
933
 
785
934
  int convert(VALUE value)
786
935
  {
787
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
788
- {
789
- return this->arg_->defaultValue<int>();
790
- }
791
- else
792
- {
793
- return FromRubyFundamental<int>::convert(value);
794
- }
936
+ return FromRubyFundamental<int>::convert(value);
795
937
  }
796
938
 
797
939
  private:
@@ -802,6 +944,8 @@ namespace Rice::detail
802
944
  class From_Ruby<int&>
803
945
  {
804
946
  public:
947
+ using Buffer_T = Buffer<int>;
948
+
805
949
  From_Ruby() = default;
806
950
 
807
951
  explicit From_Ruby(Arg* arg) : arg_(arg)
@@ -810,14 +954,22 @@ namespace Rice::detail
810
954
 
811
955
  Convertible is_convertible(VALUE value)
812
956
  {
813
- return FromRubyFundamental<int>::is_convertible(value);
957
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
958
+ {
959
+ return Convertible::Exact;
960
+ }
961
+ else
962
+ {
963
+ return FromRubyFundamental<int>::is_convertible(value);
964
+ }
814
965
  }
815
966
 
816
967
  int& convert(VALUE value)
817
968
  {
818
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
969
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
819
970
  {
820
- return this->arg_->defaultValue<int>();
971
+ Buffer_T* buffer = unwrap<Buffer_T>(value, Data_Type<Buffer_T>::ruby_data_type(), false);
972
+ return buffer->reference();
821
973
  }
822
974
  else
823
975
  {
@@ -841,32 +993,46 @@ namespace Rice::detail
841
993
  {
842
994
  }
843
995
 
844
- // Need move constructor and assignment due to std::unique_ptr
845
- From_Ruby(From_Ruby&& other) = default;
846
- From_Ruby& operator=(From_Ruby&& other) = default;
996
+ Convertible is_convertible(VALUE value)
997
+ {
998
+ return FromRubyFundamental<int*>::is_convertible(value);
999
+ }
1000
+
1001
+ int* convert(VALUE value)
1002
+ {
1003
+ return FromRubyFundamental<int*>::convert(value, this->arg_);
1004
+ }
1005
+
1006
+ private:
1007
+ Arg* arg_ = nullptr;
1008
+ };
1009
+
1010
+ template<>
1011
+ class From_Ruby<int**>
1012
+ {
1013
+ public:
1014
+ From_Ruby() = default;
847
1015
 
848
- ~From_Ruby()
1016
+ explicit From_Ruby(Arg* arg) : arg_(arg)
849
1017
  {
850
1018
  if (this->arg_ && this->arg_->isOwner())
851
1019
  {
852
- this->converted_.release();
1020
+ throw std::runtime_error("Cannot transfer ownership of an array of pointers to a fundamental type");
853
1021
  }
854
1022
  }
855
1023
 
856
1024
  Convertible is_convertible(VALUE value)
857
1025
  {
858
- return FromRubyFundamental<int*>::is_convertible(value);
1026
+ return FromRubyFundamental<int**>::is_convertible(value);
859
1027
  }
860
1028
 
861
- int* convert(VALUE value)
1029
+ int** convert(VALUE value)
862
1030
  {
863
- this->converted_ = FromRubyFundamental<int*>::convert(value);
864
- return this->converted_.get();
1031
+ return FromRubyFundamental<int**>::convert(value, this->arg_);
865
1032
  }
866
1033
 
867
1034
  private:
868
1035
  Arg* arg_ = nullptr;
869
- std::unique_ptr<int[]> converted_;
870
1036
  };
871
1037
 
872
1038
  // =========== unsigned int ============
@@ -887,14 +1053,7 @@ namespace Rice::detail
887
1053
 
888
1054
  unsigned int convert(VALUE value)
889
1055
  {
890
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
891
- {
892
- return this->arg_->defaultValue<unsigned int>();
893
- }
894
- else
895
- {
896
- return FromRubyFundamental<unsigned int>::convert(value);
897
- }
1056
+ return FromRubyFundamental<unsigned int>::convert(value);
898
1057
  }
899
1058
 
900
1059
  private:
@@ -905,6 +1064,8 @@ namespace Rice::detail
905
1064
  class From_Ruby<unsigned int&>
906
1065
  {
907
1066
  public:
1067
+ using Buffer_T = Buffer<unsigned int>;
1068
+
908
1069
  From_Ruby() = default;
909
1070
 
910
1071
  explicit From_Ruby(Arg* arg) : arg_(arg)
@@ -913,14 +1074,22 @@ namespace Rice::detail
913
1074
 
914
1075
  Convertible is_convertible(VALUE value)
915
1076
  {
916
- return FromRubyFundamental<unsigned int>::is_convertible(value);
1077
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
1078
+ {
1079
+ return Convertible::Exact;
1080
+ }
1081
+ else
1082
+ {
1083
+ return FromRubyFundamental<unsigned int>::is_convertible(value);
1084
+ }
917
1085
  }
918
1086
 
919
1087
  unsigned int& convert(VALUE value)
920
1088
  {
921
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
1089
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
922
1090
  {
923
- return this->arg_->defaultValue<unsigned int>();
1091
+ Buffer_T* buffer = unwrap<Buffer_T>(value, Data_Type<Buffer_T>::ruby_data_type(), false);
1092
+ return buffer->reference();
924
1093
  }
925
1094
  else
926
1095
  {
@@ -944,32 +1113,46 @@ namespace Rice::detail
944
1113
  {
945
1114
  }
946
1115
 
947
- // Need move constructor and assignment due to std::unique_ptr
948
- From_Ruby(From_Ruby&& other) = default;
949
- From_Ruby& operator=(From_Ruby&& other) = default;
1116
+ Convertible is_convertible(VALUE value)
1117
+ {
1118
+ return FromRubyFundamental<unsigned int*>::is_convertible(value);
1119
+ }
950
1120
 
951
- ~From_Ruby()
1121
+ unsigned int* convert(VALUE value)
1122
+ {
1123
+ return FromRubyFundamental<unsigned int*>::convert(value, this->arg_);
1124
+ }
1125
+
1126
+ private:
1127
+ Arg* arg_ = nullptr;
1128
+ };
1129
+
1130
+ template<>
1131
+ class From_Ruby<unsigned int**>
1132
+ {
1133
+ public:
1134
+ From_Ruby() = default;
1135
+
1136
+ explicit From_Ruby(Arg* arg) : arg_(arg)
952
1137
  {
953
1138
  if (this->arg_ && this->arg_->isOwner())
954
1139
  {
955
- this->converted_.release();
1140
+ throw std::runtime_error("Cannot transfer ownership of an array of pointers to a fundamental type");
956
1141
  }
957
1142
  }
958
1143
 
959
1144
  Convertible is_convertible(VALUE value)
960
1145
  {
961
- return FromRubyFundamental<unsigned int*>::is_convertible(value);
1146
+ return FromRubyFundamental<unsigned int**>::is_convertible(value);
962
1147
  }
963
1148
 
964
- unsigned int* convert(VALUE value)
1149
+ unsigned int** convert(VALUE value)
965
1150
  {
966
- this->converted_ = FromRubyFundamental<unsigned int*>::convert(value);
967
- return this->converted_.get();
1151
+ return FromRubyFundamental<unsigned int**>::convert(value, this->arg_);
968
1152
  }
969
1153
 
970
1154
  private:
971
1155
  Arg* arg_ = nullptr;
972
- std::unique_ptr<unsigned int[]> converted_;;
973
1156
  };
974
1157
 
975
1158
  // =========== long ============
@@ -990,14 +1173,7 @@ namespace Rice::detail
990
1173
 
991
1174
  long convert(VALUE value)
992
1175
  {
993
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
994
- {
995
- return this->arg_->defaultValue<long>();
996
- }
997
- else
998
- {
999
- return FromRubyFundamental<long>::convert(value);
1000
- }
1176
+ return FromRubyFundamental<long>::convert(value);
1001
1177
  }
1002
1178
 
1003
1179
  private:
@@ -1008,6 +1184,8 @@ namespace Rice::detail
1008
1184
  class From_Ruby<long&>
1009
1185
  {
1010
1186
  public:
1187
+ using Buffer_T = Buffer<long>;
1188
+
1011
1189
  From_Ruby() = default;
1012
1190
 
1013
1191
  explicit From_Ruby(Arg* arg) : arg_(arg)
@@ -1016,14 +1194,22 @@ namespace Rice::detail
1016
1194
 
1017
1195
  Convertible is_convertible(VALUE value)
1018
1196
  {
1019
- return FromRubyFundamental<long>::is_convertible(value);
1197
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
1198
+ {
1199
+ return Convertible::Exact;
1200
+ }
1201
+ else
1202
+ {
1203
+ return FromRubyFundamental<long>::is_convertible(value);
1204
+ }
1020
1205
  }
1021
1206
 
1022
1207
  long& convert(VALUE value)
1023
1208
  {
1024
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
1209
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
1025
1210
  {
1026
- return this->arg_->defaultValue<long>();
1211
+ Buffer_T* buffer = unwrap<Buffer_T>(value, Data_Type<Buffer_T>::ruby_data_type(), false);
1212
+ return buffer->reference();
1027
1213
  }
1028
1214
  else
1029
1215
  {
@@ -1034,45 +1220,59 @@ namespace Rice::detail
1034
1220
 
1035
1221
  private:
1036
1222
  Arg* arg_ = nullptr;
1037
- long converted_ = 0;
1223
+ long converted_ = 0;
1224
+ };
1225
+
1226
+ template<>
1227
+ class From_Ruby<long*>
1228
+ {
1229
+ public:
1230
+ From_Ruby() = default;
1231
+
1232
+ explicit From_Ruby(Arg* arg) : arg_(arg)
1233
+ {
1234
+ }
1235
+
1236
+ Convertible is_convertible(VALUE value)
1237
+ {
1238
+ return FromRubyFundamental<long*>::is_convertible(value);
1239
+ }
1240
+
1241
+ long* convert(VALUE value)
1242
+ {
1243
+ return FromRubyFundamental<long*>::convert(value, this->arg_);
1244
+ }
1245
+
1246
+ private:
1247
+ Arg* arg_ = nullptr;
1038
1248
  };
1039
1249
 
1040
1250
  template<>
1041
- class From_Ruby<long*>
1251
+ class From_Ruby<long**>
1042
1252
  {
1043
1253
  public:
1044
1254
  From_Ruby() = default;
1045
1255
 
1046
1256
  explicit From_Ruby(Arg* arg) : arg_(arg)
1047
- {
1048
- }
1049
-
1050
- // Need move constructor and assignment due to std::unique_ptr
1051
- From_Ruby(From_Ruby&& other) = default;
1052
- From_Ruby& operator=(From_Ruby&& other) = default;
1053
-
1054
- ~From_Ruby()
1055
1257
  {
1056
1258
  if (this->arg_ && this->arg_->isOwner())
1057
1259
  {
1058
- this->converted_.release();
1260
+ throw std::runtime_error("Cannot transfer ownership of an array of pointers to a fundamental type");
1059
1261
  }
1060
1262
  }
1061
1263
 
1062
1264
  Convertible is_convertible(VALUE value)
1063
1265
  {
1064
- return FromRubyFundamental<long*>::is_convertible(value);
1266
+ return FromRubyFundamental<long**>::is_convertible(value);
1065
1267
  }
1066
1268
 
1067
- long* convert(VALUE value)
1269
+ long** convert(VALUE value)
1068
1270
  {
1069
- this->converted_ = FromRubyFundamental<long*>::convert(value);
1070
- return this->converted_.get();
1271
+ return FromRubyFundamental<long**>::convert(value, this->arg_);
1071
1272
  }
1072
1273
 
1073
1274
  private:
1074
1275
  Arg* arg_ = nullptr;
1075
- std::unique_ptr<long[]> converted_;
1076
1276
  };
1077
1277
 
1078
1278
  // =========== unsigned long ============
@@ -1097,10 +1297,6 @@ namespace Rice::detail
1097
1297
  {
1098
1298
  return (unsigned long)value;
1099
1299
  }
1100
- else if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
1101
- {
1102
- return this->arg_->defaultValue<unsigned long>();
1103
- }
1104
1300
  else
1105
1301
  {
1106
1302
  return FromRubyFundamental<unsigned long>::convert(value);
@@ -1115,6 +1311,8 @@ namespace Rice::detail
1115
1311
  class From_Ruby<unsigned long&>
1116
1312
  {
1117
1313
  public:
1314
+ using Buffer_T = Buffer<unsigned long>;
1315
+
1118
1316
  From_Ruby() = default;
1119
1317
 
1120
1318
  explicit From_Ruby(Arg* arg) : arg_(arg)
@@ -1123,14 +1321,22 @@ namespace Rice::detail
1123
1321
 
1124
1322
  Convertible is_convertible(VALUE value)
1125
1323
  {
1126
- return FromRubyFundamental<unsigned long>::is_convertible(value);
1324
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
1325
+ {
1326
+ return Convertible::Exact;
1327
+ }
1328
+ else
1329
+ {
1330
+ return FromRubyFundamental<unsigned long>::is_convertible(value);
1331
+ }
1127
1332
  }
1128
1333
 
1129
1334
  unsigned long& convert(VALUE value)
1130
1335
  {
1131
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
1336
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
1132
1337
  {
1133
- return this->arg_->defaultValue<unsigned long>();
1338
+ Buffer_T* buffer = unwrap<Buffer_T>(value, Data_Type<Buffer_T>::ruby_data_type(), false);
1339
+ return buffer->reference();
1134
1340
  }
1135
1341
  else
1136
1342
  {
@@ -1154,32 +1360,46 @@ namespace Rice::detail
1154
1360
  {
1155
1361
  }
1156
1362
 
1157
- // Need move constructor and assignment due to std::unique_ptr
1158
- From_Ruby(From_Ruby&& other) = default;
1159
- From_Ruby& operator=(From_Ruby&& other) = default;
1363
+ Convertible is_convertible(VALUE value)
1364
+ {
1365
+ return FromRubyFundamental<unsigned long*>::is_convertible(value);
1366
+ }
1367
+
1368
+ unsigned long* convert(VALUE value)
1369
+ {
1370
+ return FromRubyFundamental<unsigned long*>::convert(value, this->arg_);
1371
+ }
1372
+
1373
+ private:
1374
+ Arg* arg_ = nullptr;
1375
+ };
1376
+
1377
+ template<>
1378
+ class From_Ruby<unsigned long**>
1379
+ {
1380
+ public:
1381
+ From_Ruby() = default;
1160
1382
 
1161
- ~From_Ruby()
1383
+ explicit From_Ruby(Arg* arg) : arg_(arg)
1162
1384
  {
1163
1385
  if (this->arg_ && this->arg_->isOwner())
1164
1386
  {
1165
- this->converted_.release();
1387
+ throw std::runtime_error("Cannot transfer ownership of an array of pointers to a fundamental type");
1166
1388
  }
1167
1389
  }
1168
1390
 
1169
1391
  Convertible is_convertible(VALUE value)
1170
1392
  {
1171
- return FromRubyFundamental<unsigned long*>::is_convertible(value);
1393
+ return FromRubyFundamental<unsigned long**>::is_convertible(value);
1172
1394
  }
1173
1395
 
1174
- unsigned long* convert(VALUE value)
1396
+ unsigned long** convert(VALUE value)
1175
1397
  {
1176
- this->converted_ = FromRubyFundamental<unsigned long*>::convert(value);
1177
- return this->converted_.get();
1398
+ return FromRubyFundamental<unsigned long**>::convert(value, this->arg_);
1178
1399
  }
1179
1400
 
1180
1401
  private:
1181
1402
  Arg* arg_ = nullptr;
1182
- std::unique_ptr<unsigned long[]> converted_;
1183
1403
  };
1184
1404
 
1185
1405
  // =========== unsigned long long ============
@@ -1204,10 +1424,6 @@ namespace Rice::detail
1204
1424
  {
1205
1425
  return value;
1206
1426
  }
1207
- else if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
1208
- {
1209
- return this->arg_->defaultValue<unsigned long long>();
1210
- }
1211
1427
  else
1212
1428
  {
1213
1429
  return FromRubyFundamental<unsigned long long>::convert(value);
@@ -1222,6 +1438,8 @@ namespace Rice::detail
1222
1438
  class From_Ruby<unsigned long long&>
1223
1439
  {
1224
1440
  public:
1441
+ using Buffer_T = Buffer<unsigned long long>;
1442
+
1225
1443
  From_Ruby() = default;
1226
1444
 
1227
1445
  explicit From_Ruby(Arg* arg) : arg_(arg)
@@ -1230,14 +1448,22 @@ namespace Rice::detail
1230
1448
 
1231
1449
  Convertible is_convertible(VALUE value)
1232
1450
  {
1233
- return FromRubyFundamental<unsigned long long>::is_convertible(value);
1451
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
1452
+ {
1453
+ return Convertible::Exact;
1454
+ }
1455
+ else
1456
+ {
1457
+ return FromRubyFundamental<unsigned long long>::is_convertible(value);
1458
+ }
1234
1459
  }
1235
1460
 
1236
1461
  unsigned long long& convert(VALUE value)
1237
1462
  {
1238
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
1463
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
1239
1464
  {
1240
- return this->arg_->defaultValue<unsigned long long>();
1465
+ Buffer_T* buffer = unwrap<Buffer_T>(value, Data_Type<Buffer_T>::ruby_data_type(), false);
1466
+ return buffer->reference();
1241
1467
  }
1242
1468
  else
1243
1469
  {
@@ -1261,42 +1487,49 @@ namespace Rice::detail
1261
1487
  {
1262
1488
  }
1263
1489
 
1264
- // Need move constructor and assignment due to std::unique_ptr
1265
- From_Ruby(From_Ruby&& other) = default;
1266
- From_Ruby& operator=(From_Ruby&& other) = default;
1490
+ Convertible is_convertible(VALUE value)
1491
+ {
1492
+ return FromRubyFundamental<unsigned long long*>::is_convertible(value);
1493
+ }
1494
+
1495
+ unsigned long long* convert(VALUE value)
1496
+ {
1497
+ return FromRubyFundamental<unsigned long long*>::convert(value, this->arg_);
1498
+ }
1499
+
1500
+ private:
1501
+ Arg* arg_ = nullptr;
1502
+ };
1503
+
1504
+ template<>
1505
+ class From_Ruby<unsigned long long**>
1506
+ {
1507
+ public:
1508
+ From_Ruby() = default;
1267
1509
 
1268
- ~From_Ruby()
1510
+ explicit From_Ruby(Arg* arg) : arg_(arg)
1269
1511
  {
1270
1512
  if (this->arg_ && this->arg_->isOwner())
1271
1513
  {
1272
- this->converted_.release();
1514
+ throw std::runtime_error("Cannot transfer ownership of an array of pointers to a fundamental type");
1273
1515
  }
1274
1516
  }
1275
1517
 
1276
1518
  Convertible is_convertible(VALUE value)
1277
1519
  {
1278
- return FromRubyFundamental<unsigned long long*>::is_convertible(value);
1520
+ return FromRubyFundamental<unsigned long long**>::is_convertible(value);
1279
1521
  }
1280
1522
 
1281
- unsigned long long* convert(VALUE value)
1523
+ unsigned long long** convert(VALUE value)
1282
1524
  {
1283
- if (value == Qnil)
1284
- {
1285
- return nullptr;
1286
- }
1287
- else
1288
- {
1289
- this->converted_ = FromRubyFundamental<unsigned long long*>::convert(value);
1290
- return this->converted_.get();
1291
- }
1525
+ return FromRubyFundamental<unsigned long long**>::convert(value, this->arg_);
1292
1526
  }
1293
1527
 
1294
1528
  private:
1295
1529
  Arg* arg_ = nullptr;
1296
- std::unique_ptr<unsigned long long[]> converted_;
1297
1530
  };
1298
-
1299
- // =========== long long ============
1531
+
1532
+ // =========== long long ============
1300
1533
  template<>
1301
1534
  class From_Ruby<long long>
1302
1535
  {
@@ -1314,14 +1547,7 @@ namespace Rice::detail
1314
1547
 
1315
1548
  long long convert(VALUE value)
1316
1549
  {
1317
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
1318
- {
1319
- return this->arg_->defaultValue<long long>();
1320
- }
1321
- else
1322
- {
1323
- return FromRubyFundamental<long long>::convert(value);
1324
- }
1550
+ return FromRubyFundamental<long long>::convert(value);
1325
1551
  }
1326
1552
 
1327
1553
  private:
@@ -1332,6 +1558,8 @@ namespace Rice::detail
1332
1558
  class From_Ruby<long long&>
1333
1559
  {
1334
1560
  public:
1561
+ using Buffer_T = Buffer<long long>;
1562
+
1335
1563
  From_Ruby() = default;
1336
1564
 
1337
1565
  explicit From_Ruby(Arg* arg) : arg_(arg)
@@ -1340,14 +1568,22 @@ namespace Rice::detail
1340
1568
 
1341
1569
  Convertible is_convertible(VALUE value)
1342
1570
  {
1343
- return FromRubyFundamental<long long>::is_convertible(value);
1571
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
1572
+ {
1573
+ return Convertible::Exact;
1574
+ }
1575
+ else
1576
+ {
1577
+ return FromRubyFundamental<long long>::is_convertible(value);
1578
+ }
1344
1579
  }
1345
1580
 
1346
1581
  long long& convert(VALUE value)
1347
1582
  {
1348
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
1583
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
1349
1584
  {
1350
- return this->arg_->defaultValue<long long>();
1585
+ Buffer_T* buffer = unwrap<Buffer_T>(value, Data_Type<Buffer_T>::ruby_data_type(), false);
1586
+ return buffer->reference();
1351
1587
  }
1352
1588
  else
1353
1589
  {
@@ -1371,32 +1607,46 @@ namespace Rice::detail
1371
1607
  {
1372
1608
  }
1373
1609
 
1374
- // Need move constructor and assignment due to std::unique_ptr
1375
- From_Ruby(From_Ruby&& other) = default;
1376
- From_Ruby& operator=(From_Ruby&& other) = default;
1610
+ Convertible is_convertible(VALUE value)
1611
+ {
1612
+ return FromRubyFundamental<long long*>::is_convertible(value);
1613
+ }
1614
+
1615
+ long long* convert(VALUE value)
1616
+ {
1617
+ return FromRubyFundamental<long long*>::convert(value, this->arg_);
1618
+ }
1619
+
1620
+ private:
1621
+ Arg* arg_ = nullptr;
1622
+ };
1623
+
1624
+ template<>
1625
+ class From_Ruby<long long**>
1626
+ {
1627
+ public:
1628
+ From_Ruby() = default;
1377
1629
 
1378
- ~From_Ruby()
1630
+ explicit From_Ruby(Arg* arg) : arg_(arg)
1379
1631
  {
1380
1632
  if (this->arg_ && this->arg_->isOwner())
1381
1633
  {
1382
- this->converted_.release();
1634
+ throw std::runtime_error("Cannot transfer ownership of an array of pointers to a fundamental type");
1383
1635
  }
1384
1636
  }
1385
1637
 
1386
1638
  Convertible is_convertible(VALUE value)
1387
1639
  {
1388
- return FromRubyFundamental<long long*>::is_convertible(value);
1640
+ return FromRubyFundamental<long long**>::is_convertible(value);
1389
1641
  }
1390
1642
 
1391
- long long* convert(VALUE value)
1643
+ long long** convert(VALUE value)
1392
1644
  {
1393
- this->converted_ = FromRubyFundamental<long long*>::convert(value);
1394
- return this->converted_.get();
1645
+ return FromRubyFundamental<long long**>::convert(value, this->arg_);
1395
1646
  }
1396
1647
 
1397
1648
  private:
1398
1649
  Arg* arg_ = nullptr;
1399
- std::unique_ptr<long long[]> converted_;
1400
1650
  };
1401
1651
 
1402
1652
  // =========== short ============
@@ -1417,14 +1667,7 @@ namespace Rice::detail
1417
1667
 
1418
1668
  short convert(VALUE value)
1419
1669
  {
1420
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
1421
- {
1422
- return this->arg_->defaultValue<short>();
1423
- }
1424
- else
1425
- {
1426
- return FromRubyFundamental<short>::convert(value);
1427
- }
1670
+ return FromRubyFundamental<short>::convert(value);
1428
1671
  }
1429
1672
 
1430
1673
  private:
@@ -1435,6 +1678,8 @@ namespace Rice::detail
1435
1678
  class From_Ruby<short&>
1436
1679
  {
1437
1680
  public:
1681
+ using Buffer_T = Buffer<short>;
1682
+
1438
1683
  From_Ruby() = default;
1439
1684
 
1440
1685
  explicit From_Ruby(Arg* arg) : arg_(arg)
@@ -1443,14 +1688,22 @@ namespace Rice::detail
1443
1688
 
1444
1689
  Convertible is_convertible(VALUE value)
1445
1690
  {
1446
- return FromRubyFundamental<short>::is_convertible(value);
1691
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
1692
+ {
1693
+ return Convertible::Exact;
1694
+ }
1695
+ else
1696
+ {
1697
+ return FromRubyFundamental<short>::is_convertible(value);
1698
+ }
1447
1699
  }
1448
1700
 
1449
1701
  short& convert(VALUE value)
1450
1702
  {
1451
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
1703
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
1452
1704
  {
1453
- return this->arg_->defaultValue<short>();
1705
+ Buffer_T* buffer = unwrap<Buffer_T>(value, Data_Type<Buffer_T>::ruby_data_type(), false);
1706
+ return buffer->reference();
1454
1707
  }
1455
1708
  else
1456
1709
  {
@@ -1474,32 +1727,45 @@ namespace Rice::detail
1474
1727
  {
1475
1728
  }
1476
1729
 
1477
- // Need move constructor and assignment due to std::unique_ptr
1478
- From_Ruby(From_Ruby&& other) = default;
1479
- From_Ruby& operator=(From_Ruby&& other) = default;
1730
+ Convertible is_convertible(VALUE value)
1731
+ {
1732
+ return FromRubyFundamental<short*>::is_convertible(value);
1733
+ }
1734
+
1735
+ short* convert(VALUE value)
1736
+ {
1737
+ return FromRubyFundamental<short*>::convert(value, this->arg_);
1738
+ }
1739
+
1740
+ private:
1741
+ Arg* arg_ = nullptr;
1742
+ };
1743
+
1744
+ template<>
1745
+ class From_Ruby<short**>
1746
+ {
1747
+ public:
1748
+ From_Ruby() = default;
1480
1749
 
1481
- ~From_Ruby()
1750
+ explicit From_Ruby(Arg* arg) : arg_(arg)
1482
1751
  {
1483
1752
  if (this->arg_ && this->arg_->isOwner())
1484
1753
  {
1485
- this->converted_.release();
1754
+ throw std::runtime_error("Cannot transfer ownership of an array of pointers to a fundamental type");
1486
1755
  }
1487
1756
  }
1488
1757
 
1489
1758
  Convertible is_convertible(VALUE value)
1490
1759
  {
1491
- return FromRubyFundamental<short*>::is_convertible(value);
1760
+ return FromRubyFundamental<short**>::is_convertible(value);
1492
1761
  }
1493
1762
 
1494
- short* convert(VALUE value)
1763
+ short** convert(VALUE value)
1495
1764
  {
1496
- this->converted_ = FromRubyFundamental<short*>::convert(value);
1497
- return this->converted_.get();
1765
+ return FromRubyFundamental<short**>::convert(value, this->arg_);
1498
1766
  }
1499
-
1500
1767
  private:
1501
1768
  Arg* arg_ = nullptr;
1502
- std::unique_ptr<short[]> converted_;
1503
1769
  };
1504
1770
 
1505
1771
  // =========== unsigned short ============
@@ -1520,14 +1786,7 @@ namespace Rice::detail
1520
1786
 
1521
1787
  unsigned short convert(VALUE value)
1522
1788
  {
1523
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
1524
- {
1525
- return this->arg_->defaultValue<unsigned short>();
1526
- }
1527
- else
1528
- {
1529
- return FromRubyFundamental<unsigned short>::convert(value);
1530
- }
1789
+ return FromRubyFundamental<unsigned short>::convert(value);
1531
1790
  }
1532
1791
 
1533
1792
  private:
@@ -1538,6 +1797,8 @@ namespace Rice::detail
1538
1797
  class From_Ruby<unsigned short&>
1539
1798
  {
1540
1799
  public:
1800
+ using Buffer_T = Buffer<unsigned short>;
1801
+
1541
1802
  From_Ruby() = default;
1542
1803
 
1543
1804
  explicit From_Ruby(Arg* arg) : arg_(arg)
@@ -1546,14 +1807,22 @@ namespace Rice::detail
1546
1807
 
1547
1808
  Convertible is_convertible(VALUE value)
1548
1809
  {
1549
- return FromRubyFundamental<unsigned short>::is_convertible(value);
1810
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
1811
+ {
1812
+ return Convertible::Exact;
1813
+ }
1814
+ else
1815
+ {
1816
+ return FromRubyFundamental<unsigned short>::is_convertible(value);
1817
+ }
1550
1818
  }
1551
1819
 
1552
1820
  unsigned short& convert(VALUE value)
1553
1821
  {
1554
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
1822
+ if (rb_type(value) == RUBY_T_DATA && Data_Type<Buffer_T>::is_descendant(value))
1555
1823
  {
1556
- return this->arg_->defaultValue<unsigned short>();
1824
+ Buffer_T* buffer = unwrap<Buffer_T>(value, Data_Type<Buffer_T>::ruby_data_type(), false);
1825
+ return buffer->reference();
1557
1826
  }
1558
1827
  else
1559
1828
  {
@@ -1577,36 +1846,51 @@ namespace Rice::detail
1577
1846
  {
1578
1847
  }
1579
1848
 
1580
- // Need move constructor and assignment due to std::unique_ptr
1581
- From_Ruby(From_Ruby&& other) = default;
1582
- From_Ruby& operator=(From_Ruby&& other) = default;
1849
+ Convertible is_convertible(VALUE value)
1850
+ {
1851
+ return FromRubyFundamental<unsigned short*>::is_convertible(value);
1852
+ }
1853
+
1854
+ unsigned short* convert(VALUE value)
1855
+ {
1856
+ return FromRubyFundamental<unsigned short*>::convert(value, this->arg_);
1857
+ }
1858
+
1859
+ private:
1860
+ Arg* arg_ = nullptr;
1861
+ };
1862
+
1863
+ template<>
1864
+ class From_Ruby<unsigned short**>
1865
+ {
1866
+ public:
1867
+ From_Ruby() = default;
1583
1868
 
1584
- ~From_Ruby()
1869
+ explicit From_Ruby(Arg* arg) : arg_(arg)
1585
1870
  {
1586
1871
  if (this->arg_ && this->arg_->isOwner())
1587
1872
  {
1588
- this->converted_.release();
1873
+ throw std::runtime_error("Cannot transfer ownership of an array of pointers to a fundamental type");
1589
1874
  }
1590
1875
  }
1591
1876
 
1592
1877
  Convertible is_convertible(VALUE value)
1593
1878
  {
1594
- return FromRubyFundamental<unsigned short*>::is_convertible(value);
1879
+ return FromRubyFundamental<unsigned short**>::is_convertible(value);
1595
1880
  }
1596
1881
 
1597
- unsigned short* convert(VALUE value)
1882
+ unsigned short** convert(VALUE value)
1598
1883
  {
1599
- this->converted_ = FromRubyFundamental<unsigned short*>::convert(value);
1600
- return this->converted_.get();
1884
+ return FromRubyFundamental<unsigned short**>::convert(value, this->arg_);
1601
1885
  }
1602
1886
 
1603
1887
  private:
1604
1888
  Arg* arg_ = nullptr;
1605
- std::unique_ptr<unsigned short[]> converted_;
1606
1889
  };
1607
1890
 
1891
+ // =========== std::nullptr_t ============
1608
1892
  template<>
1609
- class From_Ruby<void*>
1893
+ class From_Ruby<std::nullptr_t>
1610
1894
  {
1611
1895
  public:
1612
1896
  From_Ruby() = default;
@@ -1615,7 +1899,7 @@ namespace Rice::detail
1615
1899
  {
1616
1900
  if (this->arg_->isOwner())
1617
1901
  {
1618
- throw Exception(rb_eTypeError, "Cannot transfer ownership of string data to C++ void pointer");
1902
+ throw Exception(rb_eTypeError, "Cannot transfer ownership of C++ void pointer");
1619
1903
  }
1620
1904
  }
1621
1905
 
@@ -1628,11 +1912,82 @@ namespace Rice::detail
1628
1912
 
1629
1913
  switch (rb_type(value))
1630
1914
  {
1631
- case RUBY_T_DATA:
1915
+ case RUBY_T_NIL:
1632
1916
  {
1633
1917
  return Convertible::Exact;
1634
1918
  break;
1635
1919
  }
1920
+ default:
1921
+ {
1922
+ return Convertible::None;
1923
+ }
1924
+ }
1925
+ }
1926
+
1927
+ void* convert(VALUE value)
1928
+ {
1929
+ if (value == Qnil)
1930
+ {
1931
+ return nullptr;
1932
+ }
1933
+
1934
+ if (this->arg_ && this->arg_->isOpaque())
1935
+ {
1936
+ return (void*)value;
1937
+ }
1938
+
1939
+ switch (rb_type(value))
1940
+ {
1941
+ case RUBY_T_NIL:
1942
+ {
1943
+ return nullptr;
1944
+ break;
1945
+ }
1946
+ default:
1947
+ {
1948
+ throw Exception(rb_eTypeError, "wrong argument type %s (expected % s)",
1949
+ detail::protect(rb_obj_classname, value), "nil");
1950
+ }
1951
+ }
1952
+ }
1953
+ private:
1954
+ Arg* arg_ = nullptr;
1955
+ };
1956
+
1957
+ // =========== void ============
1958
+ template<>
1959
+ class From_Ruby<void*>
1960
+ {
1961
+ public:
1962
+ From_Ruby()
1963
+ {
1964
+ detail::Type<Buffer<void>>::verify();
1965
+ };
1966
+
1967
+ explicit From_Ruby(Arg* arg) : arg_(arg)
1968
+ {
1969
+ detail::Type<Buffer<void>>::verify();
1970
+
1971
+ if (this->arg_->isOwner())
1972
+ {
1973
+ throw Exception(rb_eTypeError, "Cannot transfer ownership of C++ void pointer");
1974
+ }
1975
+ }
1976
+
1977
+ Convertible is_convertible(VALUE value)
1978
+ {
1979
+ if (this->arg_ && this->arg_->isOpaque())
1980
+ {
1981
+ return Convertible::Exact;
1982
+ }
1983
+
1984
+ switch (rb_type(value))
1985
+ {
1986
+ case RUBY_T_DATA:
1987
+ {
1988
+ return Convertible::Cast;
1989
+ break;
1990
+ }
1636
1991
  case RUBY_T_STRING:
1637
1992
  {
1638
1993
  if (RB_ENCODING_IS_ASCII8BIT(value))
@@ -1655,6 +2010,11 @@ namespace Rice::detail
1655
2010
 
1656
2011
  void* convert(VALUE value)
1657
2012
  {
2013
+ if (value == Qnil)
2014
+ {
2015
+ return nullptr;
2016
+ }
2017
+
1658
2018
  if (this->arg_ && this->arg_->isOpaque())
1659
2019
  {
1660
2020
  return (void*)value;
@@ -1667,7 +2027,19 @@ namespace Rice::detail
1667
2027
  // Since C++ is not telling us type information, we need to extract it
1668
2028
  // from the Ruby object.
1669
2029
  const rb_data_type_t* rb_type = RTYPEDDATA_TYPE(value);
1670
- return detail::unwrap<void>(value, (rb_data_type_t*)rb_type, this->arg_ && this->arg_->isOwner());
2030
+
2031
+ // Is this a Buffer? It could also be a pointer to any other object being passed to
2032
+ // a C++ paramter that takes void*
2033
+ if (rb_type == Data_Type<Buffer<void>>::ruby_data_type())
2034
+ {
2035
+ Data_Object<Buffer<void>> buffer(value);
2036
+ return buffer->ptr();
2037
+ }
2038
+ else
2039
+ {
2040
+ return detail::unwrap<void>(value, (rb_data_type_t*)rb_type, this->arg_ && this->arg_->isOwner());
2041
+ }
2042
+
1671
2043
  break;
1672
2044
  }
1673
2045
  case RUBY_T_STRING: