rice 4.3.2 → 4.5.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +66 -25
- data/README.md +7 -2
- data/Rakefile +7 -1
- data/include/rice/rice.hpp +7321 -4470
- data/include/rice/stl.hpp +769 -222
- data/lib/mkmf-rice.rb +37 -95
- data/rice/Address_Registration_Guard.hpp +72 -3
- data/rice/Arg.hpp +19 -5
- data/rice/Arg.ipp +24 -0
- data/rice/Callback.hpp +21 -0
- data/rice/Callback.ipp +13 -0
- data/rice/Constructor.hpp +4 -27
- data/rice/Constructor.ipp +79 -0
- data/rice/Data_Object.hpp +74 -3
- data/rice/Data_Object.ipp +324 -32
- data/rice/Data_Type.hpp +215 -3
- data/rice/Data_Type.ipp +125 -64
- data/rice/Director.hpp +0 -2
- data/rice/Enum.hpp +4 -6
- data/rice/Enum.ipp +101 -57
- data/rice/Exception.hpp +62 -2
- data/rice/Exception.ipp +7 -12
- data/rice/JumpException.hpp +44 -0
- data/rice/JumpException.ipp +48 -0
- data/rice/MemoryView.hpp +11 -0
- data/rice/MemoryView.ipp +43 -0
- data/rice/Return.hpp +6 -26
- data/rice/Return.ipp +10 -16
- data/rice/detail/DefaultHandler.hpp +12 -0
- data/rice/detail/DefaultHandler.ipp +8 -0
- data/rice/detail/HandlerRegistry.hpp +5 -35
- data/rice/detail/HandlerRegistry.ipp +7 -11
- data/rice/detail/InstanceRegistry.hpp +1 -4
- data/rice/detail/MethodInfo.hpp +15 -5
- data/rice/detail/MethodInfo.ipp +78 -6
- data/rice/detail/Native.hpp +32 -0
- data/rice/detail/Native.ipp +129 -0
- data/rice/detail/NativeAttributeGet.hpp +51 -0
- data/rice/detail/NativeAttributeGet.ipp +51 -0
- data/rice/detail/NativeAttributeSet.hpp +43 -0
- data/rice/detail/NativeAttributeSet.ipp +82 -0
- data/rice/detail/NativeCallbackFFI.hpp +55 -0
- data/rice/detail/NativeCallbackFFI.ipp +151 -0
- data/rice/detail/NativeCallbackSimple.hpp +30 -0
- data/rice/detail/NativeCallbackSimple.ipp +29 -0
- data/rice/detail/NativeFunction.hpp +20 -21
- data/rice/detail/NativeFunction.ipp +199 -64
- data/rice/detail/NativeIterator.hpp +8 -11
- data/rice/detail/NativeIterator.ipp +27 -31
- data/rice/detail/NativeRegistry.hpp +24 -17
- data/rice/detail/NativeRegistry.ipp +23 -56
- data/rice/detail/Proc.hpp +4 -0
- data/rice/detail/Proc.ipp +85 -0
- data/rice/detail/Registries.hpp +0 -7
- data/rice/detail/Registries.ipp +0 -18
- data/rice/detail/RubyFunction.hpp +0 -3
- data/rice/detail/RubyFunction.ipp +4 -8
- data/rice/detail/RubyType.hpp +19 -0
- data/rice/detail/RubyType.ipp +187 -0
- data/rice/detail/TupleIterator.hpp +14 -0
- data/rice/detail/Type.hpp +5 -6
- data/rice/detail/Type.ipp +150 -33
- data/rice/detail/TypeRegistry.hpp +15 -7
- data/rice/detail/TypeRegistry.ipp +105 -12
- data/rice/detail/Wrapper.hpp +6 -5
- data/rice/detail/Wrapper.ipp +45 -23
- data/rice/detail/cpp_protect.hpp +5 -6
- data/rice/detail/default_allocation_func.ipp +0 -2
- data/rice/detail/from_ruby.hpp +37 -3
- data/rice/detail/from_ruby.ipp +911 -454
- data/rice/detail/ruby.hpp +18 -0
- data/rice/detail/to_ruby.hpp +41 -3
- data/rice/detail/to_ruby.ipp +437 -113
- data/rice/global_function.hpp +0 -4
- data/rice/global_function.ipp +1 -2
- data/rice/rice.hpp +105 -22
- data/rice/ruby_mark.hpp +4 -3
- data/rice/stl.hpp +4 -0
- data/test/embed_ruby.cpp +4 -1
- data/test/extconf.rb +2 -0
- data/test/ruby/test_multiple_extensions_same_class.rb +14 -14
- data/test/test_Address_Registration_Guard.cpp +5 -0
- data/test/test_Array.cpp +12 -1
- data/test/test_Attribute.cpp +103 -21
- data/test/test_Builtin_Object.cpp +5 -0
- data/test/test_Callback.cpp +231 -0
- data/test/test_Class.cpp +5 -31
- data/test/test_Constructor.cpp +69 -6
- data/test/test_Data_Object.cpp +9 -4
- data/test/test_Data_Type.cpp +428 -64
- data/test/test_Director.cpp +10 -5
- data/test/test_Enum.cpp +152 -40
- data/test/test_Exception.cpp +235 -0
- data/test/test_File.cpp +70 -0
- data/test/test_From_Ruby.cpp +542 -0
- data/test/test_Hash.cpp +5 -0
- data/test/test_Identifier.cpp +5 -0
- data/test/test_Inheritance.cpp +6 -1
- data/test/test_Iterator.cpp +5 -0
- data/test/test_JumpException.cpp +22 -0
- data/test/test_Keep_Alive.cpp +6 -1
- data/test/test_Keep_Alive_No_Wrapper.cpp +5 -0
- data/test/test_Memory_Management.cpp +5 -0
- data/test/test_Module.cpp +118 -64
- data/test/test_Native_Registry.cpp +2 -33
- data/test/test_Object.cpp +5 -0
- data/test/test_Overloads.cpp +631 -0
- data/test/test_Ownership.cpp +67 -4
- data/test/test_Proc.cpp +45 -0
- data/test/test_Self.cpp +5 -0
- data/test/test_Stl_Exception.cpp +109 -0
- data/test/test_Stl_Map.cpp +22 -8
- data/test/test_Stl_Optional.cpp +5 -0
- data/test/test_Stl_Pair.cpp +7 -2
- data/test/test_Stl_Reference_Wrapper.cpp +5 -0
- data/test/test_Stl_SmartPointer.cpp +210 -5
- data/test/test_Stl_String.cpp +5 -0
- data/test/test_Stl_String_View.cpp +5 -0
- data/test/test_Stl_Type.cpp +147 -0
- data/test/test_Stl_Unordered_Map.cpp +18 -7
- data/test/test_Stl_Variant.cpp +5 -0
- data/test/test_Stl_Vector.cpp +130 -8
- data/test/test_String.cpp +5 -0
- data/test/test_Struct.cpp +5 -0
- data/test/test_Symbol.cpp +5 -0
- data/test/test_Template.cpp +192 -0
- data/test/test_To_Ruby.cpp +152 -0
- data/test/test_Tracking.cpp +1 -0
- data/test/test_Type.cpp +100 -0
- data/test/test_global_functions.cpp +53 -6
- data/test/unittest.cpp +8 -0
- metadata +37 -20
- data/lib/version.rb +0 -3
- data/rice/Address_Registration_Guard_defn.hpp +0 -79
- data/rice/Data_Object_defn.hpp +0 -84
- data/rice/Data_Type_defn.hpp +0 -190
- data/rice/Exception_defn.hpp +0 -68
- data/rice/HandlerRegistration.hpp +0 -15
- data/rice/Identifier.hpp +0 -50
- data/rice/Identifier.ipp +0 -29
- data/rice/detail/ExceptionHandler.hpp +0 -8
- data/rice/detail/ExceptionHandler.ipp +0 -28
- data/rice/detail/ExceptionHandler_defn.hpp +0 -77
- data/rice/detail/Jump_Tag.hpp +0 -21
- data/rice/detail/NativeAttribute.hpp +0 -64
- data/rice/detail/NativeAttribute.ipp +0 -112
- data/rice/detail/from_ruby_defn.hpp +0 -38
- data/rice/detail/to_ruby_defn.hpp +0 -48
- data/test/test_Jump_Tag.cpp +0 -17
- data/test/test_To_From_Ruby.cpp +0 -399
data/rice/Data_Object.ipp
CHANGED
@@ -1,7 +1,3 @@
|
|
1
|
-
#ifndef Rice__Data_Object__ipp_
|
2
|
-
#define Rice__Data_Object__ipp_
|
3
|
-
|
4
|
-
#include "Data_Type_defn.hpp"
|
5
1
|
|
6
2
|
#include <algorithm>
|
7
3
|
|
@@ -22,6 +18,13 @@ namespace Rice
|
|
22
18
|
this->set_value(value);
|
23
19
|
}
|
24
20
|
|
21
|
+
template<typename T>
|
22
|
+
inline Data_Object<T>::Data_Object(const T& data, bool isOwner, Class klass)
|
23
|
+
{
|
24
|
+
VALUE value = detail::wrap(klass, Data_Type<T>::ruby_data_type(), data, isOwner);
|
25
|
+
this->set_value(value);
|
26
|
+
}
|
27
|
+
|
25
28
|
template<typename T>
|
26
29
|
inline Data_Object<T>::Data_Object(T* data, bool isOwner, Class klass)
|
27
30
|
{
|
@@ -65,16 +68,16 @@ namespace Rice
|
|
65
68
|
}
|
66
69
|
else
|
67
70
|
{
|
68
|
-
return detail::unwrap<T>(this->value(), Data_Type<T>::ruby_data_type());
|
71
|
+
return detail::unwrap<T>(this->value(), Data_Type<T>::ruby_data_type(), false);
|
69
72
|
}
|
70
73
|
}
|
71
74
|
|
72
75
|
template<typename T>
|
73
|
-
inline T* Data_Object<T>::from_ruby(VALUE value)
|
76
|
+
inline T* Data_Object<T>::from_ruby(VALUE value, bool takeOwnership)
|
74
77
|
{
|
75
78
|
if (Data_Type<T>::is_descendant(value))
|
76
79
|
{
|
77
|
-
return detail::unwrap<T>(value, Data_Type<T>::ruby_data_type());
|
80
|
+
return detail::unwrap<T>(value, Data_Type<T>::ruby_data_type(), takeOwnership);
|
78
81
|
}
|
79
82
|
else
|
80
83
|
{
|
@@ -102,7 +105,7 @@ namespace Rice::detail
|
|
102
105
|
VALUE convert(const T& data)
|
103
106
|
{
|
104
107
|
// Get the ruby typeinfo
|
105
|
-
|
108
|
+
std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType<T>(data);
|
106
109
|
|
107
110
|
// We always take ownership of data passed by value (yes the parameter is T& but the template
|
108
111
|
// matched <typename T> thus we have to tell wrap to copy the reference we are sending to it
|
@@ -236,6 +239,52 @@ namespace Rice::detail
|
|
236
239
|
Return* returnInfo_ = nullptr;
|
237
240
|
};
|
238
241
|
|
242
|
+
template <typename T>
|
243
|
+
class To_Ruby<T**>
|
244
|
+
{
|
245
|
+
public:
|
246
|
+
To_Ruby() = default;
|
247
|
+
|
248
|
+
explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
|
249
|
+
{
|
250
|
+
}
|
251
|
+
|
252
|
+
VALUE convert(T** data)
|
253
|
+
{
|
254
|
+
if (data)
|
255
|
+
{
|
256
|
+
// Note that T could be a pointer or reference to a base class while data is in fact a
|
257
|
+
// child class. Lookup the correct type so we return an instance of the correct Ruby class
|
258
|
+
std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType(**data);
|
259
|
+
bool isOwner = this->returnInfo_ && this->returnInfo_->isOwner();
|
260
|
+
return detail::wrap(rubyTypeInfo.first, rubyTypeInfo.second, data, isOwner);
|
261
|
+
}
|
262
|
+
else
|
263
|
+
{
|
264
|
+
return Qnil;
|
265
|
+
}
|
266
|
+
}
|
267
|
+
|
268
|
+
VALUE convert(const T** data)
|
269
|
+
{
|
270
|
+
if (data)
|
271
|
+
{
|
272
|
+
// Note that T could be a pointer or reference to a base class while data is in fact a
|
273
|
+
// child class. Lookup the correct type so we return an instance of the correct Ruby class
|
274
|
+
std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType(*data);
|
275
|
+
bool isOwner = this->returnInfo_ && this->returnInfo_->isOwner();
|
276
|
+
return detail::wrap(rubyTypeInfo.first, rubyTypeInfo.second, data, isOwner);
|
277
|
+
}
|
278
|
+
else
|
279
|
+
{
|
280
|
+
return Qnil;
|
281
|
+
}
|
282
|
+
}
|
283
|
+
|
284
|
+
private:
|
285
|
+
Return* returnInfo_ = nullptr;
|
286
|
+
};
|
287
|
+
|
239
288
|
template<typename T>
|
240
289
|
class To_Ruby<Data_Object<T>>
|
241
290
|
{
|
@@ -258,23 +307,48 @@ namespace Rice::detail
|
|
258
307
|
{
|
259
308
|
}
|
260
309
|
|
261
|
-
|
310
|
+
Convertible is_convertible(VALUE value)
|
262
311
|
{
|
263
|
-
|
264
|
-
|
312
|
+
switch (rb_type(value))
|
313
|
+
{
|
314
|
+
case RUBY_T_DATA:
|
315
|
+
return Data_Type<T>::is_descendant(value) ? Convertible::Exact : Convertible::None;
|
316
|
+
break;
|
317
|
+
default:
|
318
|
+
return Convertible::None;
|
319
|
+
}
|
265
320
|
}
|
266
321
|
|
267
322
|
T convert(VALUE value)
|
268
323
|
{
|
269
|
-
|
270
|
-
|
324
|
+
// This expression checks to see if T has an explicit copy constructor
|
325
|
+
// If it does then we have to call it directly. Not sure if this end ups
|
326
|
+
// with an extra copy or not?
|
327
|
+
//
|
328
|
+
// std::is_constructible_v<T, T> && !std::is_convertible_v<T, T>
|
271
329
|
if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
|
272
330
|
{
|
273
|
-
|
331
|
+
if constexpr (std::is_constructible_v<T, T> && !std::is_convertible_v<T, T>)
|
332
|
+
{
|
333
|
+
return T(this->arg_->template defaultValue<T>());
|
334
|
+
}
|
335
|
+
else
|
336
|
+
{
|
337
|
+
return this->arg_->template defaultValue<T>();
|
338
|
+
}
|
274
339
|
}
|
275
340
|
else
|
276
341
|
{
|
277
|
-
|
342
|
+
if constexpr (std::is_constructible_v<T, T> && !std::is_convertible_v<T, T>)
|
343
|
+
{
|
344
|
+
using Intrinsic_T = intrinsic_type<T>;
|
345
|
+
return T(*Data_Object<Intrinsic_T>::from_ruby(value, this->arg_ && this->arg_->isOwner()));
|
346
|
+
}
|
347
|
+
else
|
348
|
+
{
|
349
|
+
using Intrinsic_T = intrinsic_type<T>;
|
350
|
+
return *Data_Object<Intrinsic_T>::from_ruby(value, this->arg_ && this->arg_->isOwner());
|
351
|
+
}
|
278
352
|
}
|
279
353
|
}
|
280
354
|
|
@@ -294,10 +368,16 @@ namespace Rice::detail
|
|
294
368
|
{
|
295
369
|
}
|
296
370
|
|
297
|
-
|
371
|
+
Convertible is_convertible(VALUE value)
|
298
372
|
{
|
299
|
-
|
300
|
-
|
373
|
+
switch (rb_type(value))
|
374
|
+
{
|
375
|
+
case RUBY_T_DATA:
|
376
|
+
return Data_Type<T>::is_descendant(value) ? Convertible::Exact : Convertible::None;
|
377
|
+
break;
|
378
|
+
default:
|
379
|
+
return Convertible::None;
|
380
|
+
}
|
301
381
|
}
|
302
382
|
|
303
383
|
T& convert(VALUE value)
|
@@ -310,7 +390,7 @@ namespace Rice::detail
|
|
310
390
|
}
|
311
391
|
else
|
312
392
|
{
|
313
|
-
return *Data_Object<Intrinsic_T>::from_ruby(value);
|
393
|
+
return *Data_Object<Intrinsic_T>::from_ruby(value, this->arg_ && this->arg_->isOwner());
|
314
394
|
}
|
315
395
|
}
|
316
396
|
|
@@ -319,30 +399,154 @@ namespace Rice::detail
|
|
319
399
|
};
|
320
400
|
|
321
401
|
template<typename T>
|
322
|
-
class From_Ruby<T
|
402
|
+
class From_Ruby<T&&>
|
323
403
|
{
|
324
404
|
static_assert(!std::is_fundamental_v<intrinsic_type<T>>,
|
325
405
|
"Data_Object cannot be used with fundamental types");
|
326
406
|
public:
|
327
|
-
|
407
|
+
From_Ruby() = default;
|
408
|
+
|
409
|
+
explicit From_Ruby(Arg * arg) : arg_(arg)
|
328
410
|
{
|
329
|
-
return rb_type(value) == RUBY_T_DATA &&
|
330
|
-
Data_Type<T>::is_descendant(value);
|
331
411
|
}
|
332
412
|
|
333
|
-
|
413
|
+
Convertible is_convertible(VALUE value)
|
414
|
+
{
|
415
|
+
switch (rb_type(value))
|
416
|
+
{
|
417
|
+
case RUBY_T_DATA:
|
418
|
+
return Data_Type<T>::is_descendant(value) ? Convertible::Exact : Convertible::None;
|
419
|
+
break;
|
420
|
+
default:
|
421
|
+
return Convertible::None;
|
422
|
+
}
|
423
|
+
}
|
424
|
+
|
425
|
+
T&& convert(VALUE value)
|
334
426
|
{
|
335
427
|
using Intrinsic_T = intrinsic_type<T>;
|
336
428
|
|
337
|
-
if (value == Qnil)
|
429
|
+
if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
|
338
430
|
{
|
339
|
-
return
|
431
|
+
return std::move(this->arg_->template defaultValue<Intrinsic_T>());
|
340
432
|
}
|
341
433
|
else
|
342
434
|
{
|
343
|
-
return Data_Object<Intrinsic_T>::from_ruby(value);
|
435
|
+
return std::move(*Data_Object<Intrinsic_T>::from_ruby(value, this->arg_ && this->arg_->isOwner()));
|
436
|
+
}
|
437
|
+
}
|
438
|
+
|
439
|
+
private:
|
440
|
+
Arg* arg_ = nullptr;
|
441
|
+
};
|
442
|
+
|
443
|
+
// Helper class to convert a Ruby array of T to a C++ array of T (this happens when an API take T* as parameter
|
444
|
+
// along with a second size parameter)
|
445
|
+
template<typename T>
|
446
|
+
class ArrayHelper
|
447
|
+
{
|
448
|
+
public:
|
449
|
+
using Intrinsic_T = intrinsic_type<T>;
|
450
|
+
|
451
|
+
T* convert(VALUE value)
|
452
|
+
{
|
453
|
+
this->vector_ = Array(value).to_vector<T>();
|
454
|
+
return this->vector_.data();
|
455
|
+
}
|
456
|
+
|
457
|
+
private:
|
458
|
+
std::vector<Intrinsic_T> vector_;
|
459
|
+
};
|
460
|
+
|
461
|
+
// 99% of the time a T* represents a wrapped C++ object that we want to call methods on. However, T*
|
462
|
+
// could also be a pointer to an array of T objects, so T[]. OpenCV for example has API calls like this.
|
463
|
+
//
|
464
|
+
// Therefore this From_Ruby implementation supports both uses cases which complicates the code. The problem
|
465
|
+
// is for T[] to compile, a class needs to be constructible, destructible and not abstract. A further wrinkle
|
466
|
+
// is if T has an explicit copy-constructor then that requires additional special handling in the code
|
467
|
+
// (see From_Ruby<T>). Whether this extra complication is worth it is debatable, but it does mean that
|
468
|
+
// a Ruby array can be passed to any C++ API that takes a * including fundamental types (unsigned char)
|
469
|
+
// and class types (T).
|
470
|
+
//
|
471
|
+
// Note that the From_Ruby<T[]> specialization never matches a parameter defined in function as T[] - the C++
|
472
|
+
// compiler always picks T* instead. Not sure why...
|
473
|
+
template<typename T>
|
474
|
+
class From_Ruby<T*>
|
475
|
+
{
|
476
|
+
static_assert(!std::is_fundamental_v<intrinsic_type<T>>,
|
477
|
+
"Data_Object cannot be used with fundamental types");
|
478
|
+
using Intrinsic_T = intrinsic_type<T>;
|
479
|
+
|
480
|
+
public:
|
481
|
+
From_Ruby() = default;
|
482
|
+
|
483
|
+
explicit From_Ruby(Arg* arg) : arg_(arg)
|
484
|
+
{
|
485
|
+
}
|
486
|
+
|
487
|
+
~From_Ruby()
|
488
|
+
{
|
489
|
+
if constexpr (std::is_destructible_v<Intrinsic_T>)
|
490
|
+
{
|
491
|
+
delete this->arrayHelper_;
|
492
|
+
}
|
493
|
+
}
|
494
|
+
|
495
|
+
Convertible is_convertible(VALUE value)
|
496
|
+
{
|
497
|
+
switch (rb_type(value))
|
498
|
+
{
|
499
|
+
case RUBY_T_DATA:
|
500
|
+
return Data_Type<T>::is_descendant(value) ? Convertible::Exact : Convertible::None;
|
501
|
+
break;
|
502
|
+
case RUBY_T_NIL:
|
503
|
+
return Convertible::Exact;
|
504
|
+
break;
|
505
|
+
case RUBY_T_ARRAY:
|
506
|
+
return Convertible::Exact;
|
507
|
+
break;
|
508
|
+
default:
|
509
|
+
return Convertible::None;
|
344
510
|
}
|
345
511
|
}
|
512
|
+
|
513
|
+
T* convert(VALUE value)
|
514
|
+
{
|
515
|
+
switch (rb_type(value))
|
516
|
+
{
|
517
|
+
case RUBY_T_DATA:
|
518
|
+
{
|
519
|
+
return Data_Object<Intrinsic_T>::from_ruby(value, this->arg_ && this->arg_->isOwner());
|
520
|
+
break;
|
521
|
+
}
|
522
|
+
case RUBY_T_NIL:
|
523
|
+
{
|
524
|
+
return nullptr;
|
525
|
+
break;
|
526
|
+
}
|
527
|
+
case RUBY_T_ARRAY:
|
528
|
+
{
|
529
|
+
if constexpr (std::is_copy_constructible_v<Intrinsic_T> && std::is_destructible_v<Intrinsic_T> && !std::is_abstract_v<Intrinsic_T>)
|
530
|
+
{
|
531
|
+
if (this->arrayHelper_ == nullptr)
|
532
|
+
{
|
533
|
+
this->arrayHelper_ = new ArrayHelper<T>();
|
534
|
+
}
|
535
|
+
return this->arrayHelper_->convert(value);
|
536
|
+
break;
|
537
|
+
}
|
538
|
+
// Will fall through to the type exception if we get here
|
539
|
+
}
|
540
|
+
default:
|
541
|
+
{
|
542
|
+
throw create_type_exception<Intrinsic_T>(value);
|
543
|
+
}
|
544
|
+
}
|
545
|
+
}
|
546
|
+
|
547
|
+
private:
|
548
|
+
Arg* arg_ = nullptr;
|
549
|
+
ArrayHelper<T>* arrayHelper_ = nullptr;
|
346
550
|
};
|
347
551
|
|
348
552
|
template<typename T>
|
@@ -351,10 +555,22 @@ namespace Rice::detail
|
|
351
555
|
static_assert(!std::is_fundamental_v<intrinsic_type<T>>,
|
352
556
|
"Data_Object cannot be used with fundamental types");
|
353
557
|
public:
|
354
|
-
|
558
|
+
From_Ruby() = default;
|
559
|
+
|
560
|
+
explicit From_Ruby(Arg* arg) : arg_(arg)
|
561
|
+
{
|
562
|
+
}
|
563
|
+
|
564
|
+
Convertible is_convertible(VALUE value)
|
355
565
|
{
|
356
|
-
|
357
|
-
|
566
|
+
switch (rb_type(value))
|
567
|
+
{
|
568
|
+
case RUBY_T_DATA:
|
569
|
+
return Data_Type<T>::is_descendant(value) ? Convertible::Exact : Convertible::None;
|
570
|
+
break;
|
571
|
+
default:
|
572
|
+
return Convertible::None;
|
573
|
+
}
|
358
574
|
}
|
359
575
|
|
360
576
|
T* convert(VALUE value)
|
@@ -367,9 +583,74 @@ namespace Rice::detail
|
|
367
583
|
}
|
368
584
|
else
|
369
585
|
{
|
370
|
-
return Data_Object<Intrinsic_T>::from_ruby(value);
|
586
|
+
return Data_Object<Intrinsic_T>::from_ruby(value, this->arg_ && this->arg_->isOwner());
|
587
|
+
}
|
588
|
+
}
|
589
|
+
|
590
|
+
private:
|
591
|
+
Arg* arg_ = nullptr;
|
592
|
+
};
|
593
|
+
|
594
|
+
template<typename T>
|
595
|
+
class From_Ruby<T**>
|
596
|
+
{
|
597
|
+
static_assert(!std::is_fundamental_v<intrinsic_type<T>>,
|
598
|
+
"Data_Object cannot be used with fundamental types");
|
599
|
+
using Intrinsic_T = intrinsic_type<T>;
|
600
|
+
public:
|
601
|
+
From_Ruby() = default;
|
602
|
+
|
603
|
+
explicit From_Ruby(Arg* arg) : arg_(arg)
|
604
|
+
{
|
605
|
+
}
|
606
|
+
|
607
|
+
Convertible is_convertible(VALUE value)
|
608
|
+
{
|
609
|
+
switch (rb_type(value))
|
610
|
+
{
|
611
|
+
case RUBY_T_DATA:
|
612
|
+
return Data_Type<T>::is_descendant(value) ? Convertible::Exact : Convertible::None;
|
613
|
+
break;
|
614
|
+
case RUBY_T_NIL:
|
615
|
+
return Convertible::Exact;
|
616
|
+
break;
|
617
|
+
case RUBY_T_ARRAY:
|
618
|
+
return Convertible::Exact;
|
619
|
+
break;
|
620
|
+
default:
|
621
|
+
return Convertible::None;
|
371
622
|
}
|
372
623
|
}
|
624
|
+
|
625
|
+
T** convert(VALUE value)
|
626
|
+
{
|
627
|
+
switch (rb_type(value))
|
628
|
+
{
|
629
|
+
case RUBY_T_DATA:
|
630
|
+
{
|
631
|
+
return detail::unwrap<Intrinsic_T*>(value, Data_Type<T>::ruby_data_type(), false);
|
632
|
+
break;
|
633
|
+
}
|
634
|
+
case RUBY_T_NIL:
|
635
|
+
{
|
636
|
+
return nullptr;
|
637
|
+
break;
|
638
|
+
}
|
639
|
+
case RUBY_T_ARRAY:
|
640
|
+
{
|
641
|
+
this->vector_ = Array(value).to_vector<Intrinsic_T*>();
|
642
|
+
return this->vector_.data();
|
643
|
+
}
|
644
|
+
default:
|
645
|
+
{
|
646
|
+
throw create_type_exception<Intrinsic_T>(value);
|
647
|
+
}
|
648
|
+
}
|
649
|
+
}
|
650
|
+
|
651
|
+
private:
|
652
|
+
Arg* arg_ = nullptr;
|
653
|
+
std::vector<Intrinsic_T*> vector_;
|
373
654
|
};
|
374
655
|
|
375
656
|
template<typename T>
|
@@ -378,10 +659,21 @@ namespace Rice::detail
|
|
378
659
|
static_assert(!std::is_fundamental_v<intrinsic_type<T>>,
|
379
660
|
"Data_Object cannot be used with fundamental types");
|
380
661
|
public:
|
662
|
+
Convertible is_convertible(VALUE value)
|
663
|
+
{
|
664
|
+
switch (rb_type(value))
|
665
|
+
{
|
666
|
+
case RUBY_T_DATA:
|
667
|
+
return Data_Type<T>::is_descendant(value) ? Convertible::Exact : Convertible::None;
|
668
|
+
break;
|
669
|
+
default:
|
670
|
+
return Convertible::None;
|
671
|
+
}
|
672
|
+
}
|
673
|
+
|
381
674
|
static Data_Object<T> convert(VALUE value)
|
382
675
|
{
|
383
676
|
return Data_Object<T>(value);
|
384
677
|
}
|
385
678
|
};
|
386
679
|
}
|
387
|
-
#endif // Rice__Data_Object__ipp_
|
data/rice/Data_Type.hpp
CHANGED
@@ -1,7 +1,219 @@
|
|
1
1
|
#ifndef Rice__Data_Type__hpp_
|
2
2
|
#define Rice__Data_Type__hpp_
|
3
3
|
|
4
|
-
#include
|
5
|
-
#include "Data_Type.ipp"
|
4
|
+
#include <set>
|
6
5
|
|
7
|
-
|
6
|
+
namespace Rice
|
7
|
+
{
|
8
|
+
//! A mechanism for binding ruby types to C++ types.
|
9
|
+
/*! This class binds run-time types (Ruby VALUEs) to compile-time types
|
10
|
+
* (C++ types). The binding can occur only once.
|
11
|
+
*/
|
12
|
+
template<typename T>
|
13
|
+
class Data_Type : public Class
|
14
|
+
{
|
15
|
+
static_assert(std::is_same_v<detail::intrinsic_type<T>, T>);
|
16
|
+
|
17
|
+
public:
|
18
|
+
using type = T;
|
19
|
+
|
20
|
+
//! Default constructor which does not bind.
|
21
|
+
/*! No member functions must be called on this Data_Type except bind,
|
22
|
+
* until the type is bound.
|
23
|
+
*/
|
24
|
+
Data_Type();
|
25
|
+
|
26
|
+
//! Constructor which takes a Module.
|
27
|
+
/*! Binds the type to the given VALUE according to the rules given
|
28
|
+
* above.
|
29
|
+
* \param klass the module to which to bind.
|
30
|
+
*/
|
31
|
+
Data_Type(Module const & v);
|
32
|
+
|
33
|
+
//! Return the Ruby class.
|
34
|
+
/*! \return the ruby class to which the type is bound.
|
35
|
+
*/
|
36
|
+
static Class klass();
|
37
|
+
|
38
|
+
//! Return the Ruby data type.
|
39
|
+
static rb_data_type_t* ruby_data_type();
|
40
|
+
|
41
|
+
//! Assignment operator which takes a Module
|
42
|
+
/*! \param klass must be the class to which this data type is already
|
43
|
+
* bound.
|
44
|
+
* \return *this
|
45
|
+
*/
|
46
|
+
virtual Data_Type & operator=(Module const & klass);
|
47
|
+
|
48
|
+
/*! Creates a singleton method allocate and an instance method called
|
49
|
+
* initialize which together create a new instance of the class. The
|
50
|
+
* allocate method allocates memory for the object reference and the
|
51
|
+
* initialize method constructs the object.
|
52
|
+
* \param constructor an object that has a static member function
|
53
|
+
* construct() that constructs a new instance of T and sets the object's data
|
54
|
+
* member to point to the new instance. A helper class Constructor
|
55
|
+
* is provided that does precisely this.
|
56
|
+
* \param args a list of Arg instance used to define default parameters (optional)
|
57
|
+
*
|
58
|
+
* For example:
|
59
|
+
* \code
|
60
|
+
* define_class<Foo>("Foo")
|
61
|
+
* .define_constructor(Constructor<Foo>());
|
62
|
+
* \endcode
|
63
|
+
*/
|
64
|
+
template<typename Constructor_T, typename...Rice_Arg_Ts>
|
65
|
+
Data_Type<T>& define_constructor(Constructor_T constructor, Rice_Arg_Ts const& ...args);
|
66
|
+
|
67
|
+
/*! Runs a function that should define this Data_Types methods and attributes.
|
68
|
+
* This is useful when creating classes from a C++ class template.
|
69
|
+
*
|
70
|
+
* \param builder A function that addes methods/attributes to this class
|
71
|
+
*
|
72
|
+
* For example:
|
73
|
+
* \code
|
74
|
+
* void builder(Data_Type<Matrix<T, R, C>>& klass)
|
75
|
+
* {
|
76
|
+
* klass.define_method...
|
77
|
+
* return klass;
|
78
|
+
* }
|
79
|
+
*
|
80
|
+
* define_class<<Matrix<T, R, C>>>("Matrix")
|
81
|
+
* .build(&builder);
|
82
|
+
*
|
83
|
+
* \endcode
|
84
|
+
*/
|
85
|
+
template<typename Func_T>
|
86
|
+
Data_Type<T>& define(Func_T func);
|
87
|
+
|
88
|
+
//! Register a Director class for this class.
|
89
|
+
/*! For any class that uses Rice::Director to enable polymorphism
|
90
|
+
* across the languages, you need to register that director proxy
|
91
|
+
* class with this method. Not doing so will cause the resulting
|
92
|
+
* library to die at run time when it tries to convert the base
|
93
|
+
* type into the Director proxy type.
|
94
|
+
*
|
95
|
+
* This method takes no methodInfo, just needs the type of the
|
96
|
+
* Director proxy class.
|
97
|
+
*
|
98
|
+
* For example:
|
99
|
+
* \code
|
100
|
+
* class FooDirector : public Foo, public Rice::Director {
|
101
|
+
* ...
|
102
|
+
* };
|
103
|
+
*
|
104
|
+
* define_class<Foo>("Foo")
|
105
|
+
* .define_director<FooDirector>()
|
106
|
+
* .define_constructor(Constructor<FooDirector, Rice::Object>());
|
107
|
+
* \endcode
|
108
|
+
*/
|
109
|
+
template<typename Director_T>
|
110
|
+
Data_Type<T>& define_director();
|
111
|
+
|
112
|
+
//! Determine if the type is bound.
|
113
|
+
/*! \return true if the object is bound, false otherwise.
|
114
|
+
*/
|
115
|
+
static bool is_bound();
|
116
|
+
static void check_is_bound();
|
117
|
+
static bool is_defined(Object parent, const std::string& name);
|
118
|
+
|
119
|
+
// This is only for testing - DO NOT USE!!!
|
120
|
+
static void unbind();
|
121
|
+
|
122
|
+
static bool is_descendant(VALUE value);
|
123
|
+
|
124
|
+
//! Define an iterator.
|
125
|
+
/*! Essentially this is a conversion from a C++-style begin/end
|
126
|
+
* iterator to a Ruby-style \#each iterator.
|
127
|
+
* \param begin a member function pointer to a function that returns
|
128
|
+
* an iterator to the beginning of the sequence.
|
129
|
+
* \param end a member function pointer to a function that returns an
|
130
|
+
* iterator to the end of the sequence.
|
131
|
+
* \param name the name of the iterator.
|
132
|
+
* \return *this
|
133
|
+
*/
|
134
|
+
|
135
|
+
template<typename Iterator_Func_T>
|
136
|
+
Data_Type<T>& define_iterator(Iterator_Func_T begin, Iterator_Func_T end, std::string name = "each");
|
137
|
+
|
138
|
+
template <typename Attribute_T>
|
139
|
+
Data_Type<T>& define_attr(std::string name, Attribute_T attribute, AttrAccess access = AttrAccess::ReadWrite);
|
140
|
+
|
141
|
+
template <typename Attribute_T>
|
142
|
+
Data_Type<T>& define_singleton_attr(std::string name, Attribute_T attribute, AttrAccess access = AttrAccess::ReadWrite);
|
143
|
+
|
144
|
+
#include "cpp_api/shared_methods.hpp"
|
145
|
+
protected:
|
146
|
+
//! Bind a Data_Type to a VALUE.
|
147
|
+
/*! Throws an exception if the Data_Type is already bound to a
|
148
|
+
* different class. Any existing instances of the Data_Type will be
|
149
|
+
* bound after this function returns.
|
150
|
+
* \param klass the ruby type to which to bind.
|
151
|
+
* \return *this
|
152
|
+
*/
|
153
|
+
template <typename Base_T = void>
|
154
|
+
static Data_Type<T> bind(const Module& klass);
|
155
|
+
|
156
|
+
template<typename T_, typename Base_T>
|
157
|
+
friend Rice::Data_Type<T_> define_class_under(Object parent, Identifier id, Class superKlass);
|
158
|
+
|
159
|
+
template<typename T_, typename Base_T>
|
160
|
+
friend Rice::Data_Type<T_> define_class_under(Object parent, char const * name);
|
161
|
+
|
162
|
+
template<typename T_, typename Base_T>
|
163
|
+
friend Rice::Data_Type<T_> define_class(char const * name);
|
164
|
+
|
165
|
+
template<bool IsMethod, typename Function_T>
|
166
|
+
void wrap_native_call(VALUE klass, std::string name, Function_T&& function, MethodInfo* methodInfo);
|
167
|
+
|
168
|
+
private:
|
169
|
+
template<typename T_>
|
170
|
+
friend class Data_Type;
|
171
|
+
|
172
|
+
static inline VALUE klass_ = Qnil;
|
173
|
+
|
174
|
+
// Typed Data support
|
175
|
+
static inline rb_data_type_t* rb_data_type_ = nullptr;
|
176
|
+
|
177
|
+
// Track unbound instances (ie, declared variables of type Data_Type<T>
|
178
|
+
// before define_class is called)
|
179
|
+
static inline std::set<Data_Type<T>*>unbound_instances_;
|
180
|
+
};
|
181
|
+
|
182
|
+
//! Define a new data class in the namespace given by module.
|
183
|
+
/*! This override allows you to specify a Ruby class as the base class versus a
|
184
|
+
* wrapped C++ class. This functionality is rarely needed - but is essential for
|
185
|
+
* creating new custom Exception classes where the Ruby superclass should be
|
186
|
+
* rb_eStandard
|
187
|
+
* \param T the C++ type of the wrapped class.
|
188
|
+
* \param module the Module in which to define the class.
|
189
|
+
* \param name the name of the new class.
|
190
|
+
* \param superKlass the Ruby super class.
|
191
|
+
* \return the new class.
|
192
|
+
*/
|
193
|
+
template<typename T, typename Base_T = void>
|
194
|
+
Data_Type<T> define_class_under(Object parent, Identifier id, Class superKlass = rb_cObject);
|
195
|
+
|
196
|
+
//! Define a new data class in the namespace given by module.
|
197
|
+
/*! By default the class will inherit from Ruby's rb_cObject. This
|
198
|
+
* can be overriden via the Base_T template parameter. Note that
|
199
|
+
* Base_T must already have been registered.
|
200
|
+
* \param T the C++ type of the wrapped class.
|
201
|
+
* \param module the the Module in which to define the class.
|
202
|
+
* \return the new class.
|
203
|
+
*/
|
204
|
+
template<typename T, typename Base_T = void>
|
205
|
+
Data_Type<T> define_class_under(Object parent, char const* name);
|
206
|
+
|
207
|
+
//! Define a new data class in the default namespace.
|
208
|
+
/*! By default the class will inherit from Ruby's rb_cObject. This
|
209
|
+
* can be overriden via the Base_T template parameter. Note that
|
210
|
+
* Base_T must already have been registered.
|
211
|
+
* \param T the C++ type of the wrapped class.
|
212
|
+
* \param module the the Module in which to define the class.
|
213
|
+
* \return the new class.
|
214
|
+
*/
|
215
|
+
template<typename T, typename Base_T = void>
|
216
|
+
Data_Type<T> define_class(char const* name);
|
217
|
+
}
|
218
|
+
|
219
|
+
#endif // Rice__Data_Type__hpp_
|