rice 4.8.0 → 4.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +25 -1
- data/CMakePresets.json +77 -50
- data/FindRuby.cmake +1 -1
- data/bin/rice-doc.rb +2 -0
- data/include/rice/api.hpp +14 -1
- data/include/rice/rice.hpp +351 -132
- data/include/rice/stl.hpp +319 -256
- data/lib/rice/doc/config.rb +57 -57
- data/lib/rice/doc/cpp_reference.rb +158 -158
- data/lib/rice/doc/doxygen.rb +289 -289
- data/lib/rice/doc/mkdocs.rb +332 -332
- data/lib/rice/doc/rice.rb +48 -47
- data/lib/rice/doc/ruby.rb +26 -26
- data/lib/rice/native.rb +15 -15
- data/lib/rice/native_registry.rb +12 -17
- data/lib/rice/parameter.rb +5 -5
- data/lib/rice/rbs.rb +72 -72
- data/lib/rice/version.rb +1 -1
- data/lib/rubygems/builder.rb +9 -9
- data/lib/rubygems_plugin.rb +8 -8
- data/rice/Data_Type.ipp +12 -7
- data/rice/cpp_api/Class.hpp +5 -0
- data/rice/cpp_api/Class.ipp +5 -0
- data/rice/cpp_api/Object.hpp +6 -0
- data/rice/cpp_api/Object.ipp +5 -0
- data/rice/detail/Forwards.hpp +18 -0
- data/rice/detail/Forwards.ipp +60 -0
- data/rice/detail/Native.ipp +2 -4
- data/rice/detail/NativeAttributeGet.ipp +1 -1
- data/rice/detail/NativeAttributeSet.hpp +5 -3
- data/rice/detail/NativeAttributeSet.ipp +41 -33
- data/rice/detail/NativeMethod.ipp +25 -22
- data/rice/detail/NativeRegistry.hpp +4 -2
- data/rice/detail/NativeRegistry.ipp +42 -9
- data/rice/detail/Parameter.ipp +3 -4
- data/rice/detail/Type.ipp +4 -0
- data/rice/detail/Wrapper.hpp +17 -12
- data/rice/detail/Wrapper.ipp +95 -36
- data/rice/rice.hpp +3 -0
- data/rice/rice_api/NativeRegistry.ipp +14 -1
- data/rice/stl/exception.ipp +1 -1
- data/rice/stl/filesystem.ipp +1 -1
- data/rice/stl/map.ipp +13 -11
- data/rice/stl/multimap.ipp +13 -11
- data/rice/stl/pair.ipp +14 -8
- data/rice/stl/set.ipp +16 -16
- data/rice/stl/shared_ptr.hpp +16 -0
- data/rice/stl/shared_ptr.ipp +74 -37
- data/rice/stl/type_index.ipp +1 -1
- data/rice/stl/unique_ptr.hpp +9 -3
- data/rice/stl/unique_ptr.ipp +80 -124
- data/rice/stl/unordered_map.ipp +14 -12
- data/rice/stl/vector.ipp +67 -31
- data/test/test_Attribute.cpp +72 -0
- data/test/test_Callback.cpp +3 -0
- data/test/test_Inheritance.cpp +14 -14
- data/test/test_Keep_Alive_No_Wrapper.cpp +6 -2
- data/test/test_Stl_Map.cpp +46 -0
- data/test/test_Stl_Multimap.cpp +46 -0
- data/test/test_Stl_Set.cpp +34 -0
- data/test/test_Stl_SharedPtr.cpp +160 -45
- data/test/test_Stl_UniquePtr.cpp +48 -3
- data/test/test_Stl_Unordered_Map.cpp +46 -0
- data/test/test_Stl_Variant.cpp +10 -14
- data/test/test_Stl_Vector.cpp +140 -13
- data/test/test_Tracking.cpp +3 -0
- metadata +3 -1
data/include/rice/rice.hpp
CHANGED
|
@@ -600,9 +600,13 @@ namespace Rice::detail
|
|
|
600
600
|
class WrapperBase
|
|
601
601
|
{
|
|
602
602
|
public:
|
|
603
|
-
|
|
603
|
+
static void addKeepAlive(VALUE object, VALUE keepAlive);
|
|
604
|
+
static bool isConst(VALUE object);
|
|
605
|
+
|
|
606
|
+
public:
|
|
607
|
+
WrapperBase(rb_data_type_t* rb_data_type);
|
|
604
608
|
virtual ~WrapperBase() = default;
|
|
605
|
-
virtual void* get() = 0;
|
|
609
|
+
virtual void* get(rb_data_type_t* requestedType) = 0;
|
|
606
610
|
bool isConst();
|
|
607
611
|
|
|
608
612
|
void ruby_mark();
|
|
@@ -610,6 +614,7 @@ namespace Rice::detail
|
|
|
610
614
|
void setOwner(bool value);
|
|
611
615
|
|
|
612
616
|
protected:
|
|
617
|
+
rb_data_type_t* rb_data_type_;
|
|
613
618
|
bool isOwner_ = false;
|
|
614
619
|
bool isConst_ = false;
|
|
615
620
|
|
|
@@ -624,10 +629,10 @@ namespace Rice::detail
|
|
|
624
629
|
class Wrapper : public WrapperBase
|
|
625
630
|
{
|
|
626
631
|
public:
|
|
627
|
-
Wrapper(T& data);
|
|
628
|
-
Wrapper(T&& data);
|
|
632
|
+
Wrapper(rb_data_type_t* rb_data_type, T& data);
|
|
633
|
+
Wrapper(rb_data_type_t* rb_data_type, T&& data);
|
|
629
634
|
~Wrapper();
|
|
630
|
-
void* get() override;
|
|
635
|
+
void* get(rb_data_type_t* requestedType) override;
|
|
631
636
|
|
|
632
637
|
private:
|
|
633
638
|
T data_;
|
|
@@ -637,9 +642,9 @@ namespace Rice::detail
|
|
|
637
642
|
class Wrapper<T&> : public WrapperBase
|
|
638
643
|
{
|
|
639
644
|
public:
|
|
640
|
-
Wrapper(T& data);
|
|
645
|
+
Wrapper(rb_data_type_t* rb_data_type, T& data);
|
|
641
646
|
~Wrapper();
|
|
642
|
-
void* get() override;
|
|
647
|
+
void* get(rb_data_type_t* requestedType) override;
|
|
643
648
|
|
|
644
649
|
private:
|
|
645
650
|
T& data_;
|
|
@@ -649,9 +654,9 @@ namespace Rice::detail
|
|
|
649
654
|
class Wrapper<T*> : public WrapperBase
|
|
650
655
|
{
|
|
651
656
|
public:
|
|
652
|
-
Wrapper(T* data, bool isOwner);
|
|
657
|
+
Wrapper(rb_data_type_t* rb_data_type, T* data, bool isOwner);
|
|
653
658
|
~Wrapper();
|
|
654
|
-
void* get() override;
|
|
659
|
+
void* get(rb_data_type_t* requestedType) override;
|
|
655
660
|
|
|
656
661
|
private:
|
|
657
662
|
T* data_ = nullptr;
|
|
@@ -661,9 +666,9 @@ namespace Rice::detail
|
|
|
661
666
|
class Wrapper<T**> : public WrapperBase
|
|
662
667
|
{
|
|
663
668
|
public:
|
|
664
|
-
Wrapper(T** data, bool isOwner);
|
|
669
|
+
Wrapper(rb_data_type_t* rb_data_type, T** data, bool isOwner);
|
|
665
670
|
~Wrapper();
|
|
666
|
-
void* get() override;
|
|
671
|
+
void* get(rb_data_type_t* requestedType) override;
|
|
667
672
|
|
|
668
673
|
private:
|
|
669
674
|
T** data_ = nullptr;
|
|
@@ -671,7 +676,7 @@ namespace Rice::detail
|
|
|
671
676
|
|
|
672
677
|
// ---- Helper Functions ---------
|
|
673
678
|
template <typename T>
|
|
674
|
-
|
|
679
|
+
Wrapper<T*>* wrapConstructed(VALUE value, rb_data_type_t* rb_data_type, T* data);
|
|
675
680
|
|
|
676
681
|
template <typename T>
|
|
677
682
|
VALUE wrap(VALUE klass, rb_data_type_t* rb_data_type, T& data, bool isOwner);
|
|
@@ -1609,6 +1614,7 @@ namespace Rice
|
|
|
1609
1614
|
namespace Rice
|
|
1610
1615
|
{
|
|
1611
1616
|
class Class;
|
|
1617
|
+
class Module;
|
|
1612
1618
|
class String;
|
|
1613
1619
|
class Array;
|
|
1614
1620
|
|
|
@@ -1716,6 +1722,11 @@ namespace Rice
|
|
|
1716
1722
|
*/
|
|
1717
1723
|
bool is_a(Object klass) const;
|
|
1718
1724
|
|
|
1725
|
+
//! Extend the object with a module.
|
|
1726
|
+
/*! \param mod the module to extend with.
|
|
1727
|
+
*/
|
|
1728
|
+
void extend(Module const& mod);
|
|
1729
|
+
|
|
1719
1730
|
//! Determine if the objects responds to a method.
|
|
1720
1731
|
/*! \param id the name of the method
|
|
1721
1732
|
* \return true if the objects responds to the method, false
|
|
@@ -2697,6 +2708,11 @@ namespace Rice
|
|
|
2697
2708
|
*/
|
|
2698
2709
|
const std::string base_name() const;
|
|
2699
2710
|
|
|
2711
|
+
//! Return the superclass of this class
|
|
2712
|
+
/*! \return Class.
|
|
2713
|
+
*/
|
|
2714
|
+
Class superclass() const;
|
|
2715
|
+
|
|
2700
2716
|
// Include these methods to call methods from Module but return
|
|
2701
2717
|
// an instance of the current classes. This is an alternative to
|
|
2702
2718
|
// using CRTP.
|
|
@@ -3008,8 +3024,9 @@ namespace Rice
|
|
|
3008
3024
|
using Receiver_T = typename attribute_traits<Attribute_T>::class_type;
|
|
3009
3025
|
|
|
3010
3026
|
public:
|
|
3011
|
-
// Register attribute
|
|
3012
|
-
|
|
3027
|
+
// Register attribute setter with Ruby
|
|
3028
|
+
template<typename...Arg_Ts>
|
|
3029
|
+
static void define(VALUE klass, std::string name, Attribute_T attribute, Arg_Ts&...args);
|
|
3013
3030
|
|
|
3014
3031
|
public:
|
|
3015
3032
|
// Disallow creating/copying/moving
|
|
@@ -3027,11 +3044,12 @@ namespace Rice
|
|
|
3027
3044
|
VALUE returnKlass() override;
|
|
3028
3045
|
|
|
3029
3046
|
protected:
|
|
3030
|
-
NativeAttributeSet(VALUE klass, std::string name, Attribute_T attr);
|
|
3047
|
+
NativeAttributeSet(VALUE klass, std::string name, Attribute_T attr, std::unique_ptr<Parameter<T_Unqualified>> parameter);
|
|
3031
3048
|
|
|
3032
3049
|
private:
|
|
3033
3050
|
VALUE klass_;
|
|
3034
3051
|
Attribute_T attribute_;
|
|
3052
|
+
std::unique_ptr<Parameter<T_Unqualified>> parameter_;
|
|
3035
3053
|
};
|
|
3036
3054
|
} // detail
|
|
3037
3055
|
} // Rice
|
|
@@ -3792,10 +3810,12 @@ namespace Rice::detail
|
|
|
3792
3810
|
NativeRegistry& operator=(const NativeRegistry& other) = delete;
|
|
3793
3811
|
|
|
3794
3812
|
void add(VALUE klass, ID methodId, std::unique_ptr<Native>& native);
|
|
3813
|
+
void replace(VALUE klass, ID methodId, std::unique_ptr<Native>& native);
|
|
3795
3814
|
void reset(VALUE klass);
|
|
3796
3815
|
|
|
3797
|
-
|
|
3798
|
-
|
|
3816
|
+
std::vector<Native*> lookup(VALUE klass);
|
|
3817
|
+
std::vector<std::unique_ptr<Native>>& lookup(VALUE klass, ID methodId);
|
|
3818
|
+
std::vector<Native*> lookup(VALUE klass, NativeKind kind);
|
|
3799
3819
|
|
|
3800
3820
|
private:
|
|
3801
3821
|
// Key - Ruby klass/method
|
|
@@ -3963,17 +3983,16 @@ namespace Rice::detail
|
|
|
3963
3983
|
// One caveat - procs are also RUBY_T_DATA so don't check if this is a function type
|
|
3964
3984
|
if (result == Convertible::Exact && rb_type(value) == RUBY_T_DATA && !std::is_function_v<std::remove_pointer_t<T>>)
|
|
3965
3985
|
{
|
|
3966
|
-
|
|
3967
|
-
WrapperBase* wrapper = getWrapper(value);
|
|
3986
|
+
bool isConst = WrapperBase::isConst(value);
|
|
3968
3987
|
|
|
3969
3988
|
// Do not send a const value to a non-const parameter
|
|
3970
|
-
if (
|
|
3989
|
+
if (isConst && !is_const_any_v<T>)
|
|
3971
3990
|
{
|
|
3972
3991
|
result = Convertible::None;
|
|
3973
3992
|
}
|
|
3974
3993
|
// It is ok to send a non-const value to a const parameter but
|
|
3975
3994
|
// prefer non-const to non-const by slightly decreasing the score
|
|
3976
|
-
else if (!
|
|
3995
|
+
else if (!isConst && is_const_any_v<T>)
|
|
3977
3996
|
{
|
|
3978
3997
|
result = Convertible::ConstMismatch;
|
|
3979
3998
|
}
|
|
@@ -8916,17 +8935,21 @@ namespace Rice::detail
|
|
|
8916
8935
|
{
|
|
8917
8936
|
inline void NativeRegistry::add(VALUE klass, ID methodId, std::unique_ptr<Native>& native)
|
|
8918
8937
|
{
|
|
8919
|
-
|
|
8920
|
-
|
|
8921
|
-
klass = detail::protect(rb_class_of, klass);
|
|
8922
|
-
}
|
|
8938
|
+
// Lookup items for method
|
|
8939
|
+
std::vector<std::unique_ptr<Native>>& natives = NativeRegistry::lookup(klass, methodId);
|
|
8923
8940
|
|
|
8924
|
-
//
|
|
8925
|
-
std::
|
|
8941
|
+
// Add new native
|
|
8942
|
+
natives.push_back(std::move(native));
|
|
8943
|
+
}
|
|
8926
8944
|
|
|
8945
|
+
inline void NativeRegistry::replace(VALUE klass, ID methodId, std::unique_ptr<Native>& native)
|
|
8946
|
+
{
|
|
8927
8947
|
// Lookup items for method
|
|
8928
|
-
std::vector<std::unique_ptr<Native>>& natives =
|
|
8948
|
+
std::vector<std::unique_ptr<Native>>& natives = NativeRegistry::lookup(klass, methodId);
|
|
8929
8949
|
|
|
8950
|
+
// Clear existing natives
|
|
8951
|
+
natives.clear();
|
|
8952
|
+
// Add new native
|
|
8930
8953
|
natives.push_back(std::move(native));
|
|
8931
8954
|
}
|
|
8932
8955
|
|
|
@@ -8946,7 +8969,7 @@ namespace Rice::detail
|
|
|
8946
8969
|
}
|
|
8947
8970
|
}
|
|
8948
8971
|
|
|
8949
|
-
inline
|
|
8972
|
+
inline std::vector<Native*> NativeRegistry::lookup(VALUE klass)
|
|
8950
8973
|
{
|
|
8951
8974
|
std::vector<Native*> result;
|
|
8952
8975
|
|
|
@@ -8972,7 +8995,7 @@ namespace Rice::detail
|
|
|
8972
8995
|
return result;
|
|
8973
8996
|
}
|
|
8974
8997
|
|
|
8975
|
-
inline
|
|
8998
|
+
inline std::vector<std::unique_ptr<Native>>& NativeRegistry::lookup(VALUE klass, ID methodId)
|
|
8976
8999
|
{
|
|
8977
9000
|
if (rb_type(klass) == T_ICLASS)
|
|
8978
9001
|
{
|
|
@@ -8985,6 +9008,35 @@ namespace Rice::detail
|
|
|
8985
9008
|
// Lookup items for method
|
|
8986
9009
|
return this->natives_[key];
|
|
8987
9010
|
}
|
|
9011
|
+
|
|
9012
|
+
inline std::vector<Native*> NativeRegistry::lookup(VALUE klass, NativeKind kind)
|
|
9013
|
+
{
|
|
9014
|
+
std::vector<Native*> result;
|
|
9015
|
+
|
|
9016
|
+
if (rb_type(klass) == T_ICLASS)
|
|
9017
|
+
{
|
|
9018
|
+
klass = detail::protect(rb_class_of, klass);
|
|
9019
|
+
}
|
|
9020
|
+
|
|
9021
|
+
for (auto& pair : this->natives_)
|
|
9022
|
+
{
|
|
9023
|
+
const std::pair<VALUE, ID>& key = pair.first;
|
|
9024
|
+
|
|
9025
|
+
if (klass == key.first)
|
|
9026
|
+
{
|
|
9027
|
+
const std::vector<std::unique_ptr<Native>>& natives = pair.second;
|
|
9028
|
+
for (auto& native : natives)
|
|
9029
|
+
{
|
|
9030
|
+
if (native->kind() == kind)
|
|
9031
|
+
{
|
|
9032
|
+
result.push_back(native.get());
|
|
9033
|
+
}
|
|
9034
|
+
}
|
|
9035
|
+
}
|
|
9036
|
+
}
|
|
9037
|
+
|
|
9038
|
+
return result;
|
|
9039
|
+
}
|
|
8988
9040
|
}
|
|
8989
9041
|
|
|
8990
9042
|
// ========= Registries.ipp =========
|
|
@@ -9207,6 +9259,10 @@ namespace Rice::detail
|
|
|
9207
9259
|
std::regex equalRegex(R"(,\s*std::equal_to)");
|
|
9208
9260
|
removeGroup(base, equalRegex);
|
|
9209
9261
|
|
|
9262
|
+
// Remove default_delete (std::unique_ptr)
|
|
9263
|
+
std::regex defaultDeleteRegex(R"(,\s*std::default_delete)");
|
|
9264
|
+
removeGroup(base, defaultDeleteRegex);
|
|
9265
|
+
|
|
9210
9266
|
// Remove spaces before pointers
|
|
9211
9267
|
std::regex ptrRegex = std::regex(R"(\s+\*)");
|
|
9212
9268
|
base = std::regex_replace(base, ptrRegex, "*");
|
|
@@ -9531,6 +9587,22 @@ namespace Rice::detail
|
|
|
9531
9587
|
|
|
9532
9588
|
namespace Rice::detail
|
|
9533
9589
|
{
|
|
9590
|
+
inline void WrapperBase::addKeepAlive(VALUE object, VALUE keepAlive)
|
|
9591
|
+
{
|
|
9592
|
+
WrapperBase* wrapper = getWrapper(object);
|
|
9593
|
+
wrapper->addKeepAlive(keepAlive);
|
|
9594
|
+
}
|
|
9595
|
+
|
|
9596
|
+
inline bool WrapperBase::isConst(VALUE object)
|
|
9597
|
+
{
|
|
9598
|
+
WrapperBase* wrapper = getWrapper(object);
|
|
9599
|
+
return wrapper->isConst();
|
|
9600
|
+
}
|
|
9601
|
+
|
|
9602
|
+
inline WrapperBase::WrapperBase(rb_data_type_t* rb_data_type) : rb_data_type_(rb_data_type)
|
|
9603
|
+
{
|
|
9604
|
+
}
|
|
9605
|
+
|
|
9534
9606
|
inline bool WrapperBase::isConst()
|
|
9535
9607
|
{
|
|
9536
9608
|
return this->isConst_;
|
|
@@ -9556,31 +9628,40 @@ namespace Rice::detail
|
|
|
9556
9628
|
|
|
9557
9629
|
// ---- Wrapper -----
|
|
9558
9630
|
template <typename T>
|
|
9559
|
-
inline Wrapper<T>::Wrapper(T& data): data_(data)
|
|
9631
|
+
inline Wrapper<T>::Wrapper(rb_data_type_t* rb_data_type, T& data) : WrapperBase(rb_data_type), data_(data)
|
|
9560
9632
|
{
|
|
9561
9633
|
this->isConst_ = std::is_const_v<std::remove_reference_t<T>>;
|
|
9562
9634
|
}
|
|
9563
9635
|
|
|
9564
9636
|
template <typename T>
|
|
9565
|
-
inline Wrapper<T>::Wrapper(T&& data) : data_(std::move(data))
|
|
9637
|
+
inline Wrapper<T>::Wrapper(rb_data_type_t* rb_data_type, T&& data) : WrapperBase(rb_data_type), data_(std::move(data))
|
|
9566
9638
|
{
|
|
9567
9639
|
}
|
|
9568
9640
|
|
|
9569
9641
|
template <typename T>
|
|
9570
9642
|
inline Wrapper<T>::~Wrapper()
|
|
9571
9643
|
{
|
|
9572
|
-
Registries::instance.instances.remove(this->get());
|
|
9644
|
+
Registries::instance.instances.remove(this->get(this->rb_data_type_));
|
|
9573
9645
|
}
|
|
9574
9646
|
|
|
9575
9647
|
template <typename T>
|
|
9576
|
-
inline void* Wrapper<T>::
|
|
9648
|
+
inline void* Wrapper<T>::get(rb_data_type_t* requestedType)
|
|
9577
9649
|
{
|
|
9578
|
-
|
|
9650
|
+
if (rb_typeddata_inherited_p(this->rb_data_type_, requestedType))
|
|
9651
|
+
{
|
|
9652
|
+
return (void*)&this->data_;
|
|
9653
|
+
}
|
|
9654
|
+
else
|
|
9655
|
+
{
|
|
9656
|
+
throw Exception(rb_eTypeError, "wrong argument type %s (expected %s)",
|
|
9657
|
+
this->rb_data_type_->wrap_struct_name,
|
|
9658
|
+
requestedType->wrap_struct_name);
|
|
9659
|
+
}
|
|
9579
9660
|
}
|
|
9580
9661
|
|
|
9581
9662
|
// ---- Wrapper& -----
|
|
9582
9663
|
template <typename T>
|
|
9583
|
-
inline Wrapper<T&>::Wrapper(T& data): data_(data)
|
|
9664
|
+
inline Wrapper<T&>::Wrapper(rb_data_type_t* rb_data_type, T& data) : WrapperBase(rb_data_type), data_(data)
|
|
9584
9665
|
{
|
|
9585
9666
|
this->isConst_ = std::is_const_v<std::remove_reference_t<T>>;
|
|
9586
9667
|
}
|
|
@@ -9588,18 +9669,27 @@ namespace Rice::detail
|
|
|
9588
9669
|
template <typename T>
|
|
9589
9670
|
inline Wrapper<T&>::~Wrapper()
|
|
9590
9671
|
{
|
|
9591
|
-
Registries::instance.instances.remove(this->get());
|
|
9672
|
+
Registries::instance.instances.remove(this->get(this->rb_data_type_));
|
|
9592
9673
|
}
|
|
9593
9674
|
|
|
9594
9675
|
template <typename T>
|
|
9595
|
-
inline void* Wrapper<T&>::get()
|
|
9676
|
+
inline void* Wrapper<T&>::get(rb_data_type_t* requestedType)
|
|
9596
9677
|
{
|
|
9597
|
-
|
|
9678
|
+
if (rb_typeddata_inherited_p(this->rb_data_type_, requestedType))
|
|
9679
|
+
{
|
|
9680
|
+
return (void*)&this->data_;
|
|
9681
|
+
}
|
|
9682
|
+
else
|
|
9683
|
+
{
|
|
9684
|
+
throw Exception(rb_eTypeError, "wrong argument type %s (expected %s)",
|
|
9685
|
+
this->rb_data_type_->wrap_struct_name,
|
|
9686
|
+
requestedType->wrap_struct_name);
|
|
9687
|
+
}
|
|
9598
9688
|
}
|
|
9599
9689
|
|
|
9600
9690
|
// ---- Wrapper* -----
|
|
9601
9691
|
template <typename T>
|
|
9602
|
-
inline Wrapper<T*>::Wrapper(T* data, bool isOwner) : data_(data)
|
|
9692
|
+
inline Wrapper<T*>::Wrapper(rb_data_type_t* rb_data_type, T* data, bool isOwner) : WrapperBase(rb_data_type), data_(data)
|
|
9603
9693
|
{
|
|
9604
9694
|
this->isOwner_ = isOwner;
|
|
9605
9695
|
this->isConst_ = std::is_const_v<std::remove_pointer_t<T>>;
|
|
@@ -9608,7 +9698,8 @@ namespace Rice::detail
|
|
|
9608
9698
|
template <typename T>
|
|
9609
9699
|
inline Wrapper<T*>::~Wrapper()
|
|
9610
9700
|
{
|
|
9611
|
-
Registries::instance.instances.remove(this->get());
|
|
9701
|
+
Registries::instance.instances.remove(this->get(this->rb_data_type_));
|
|
9702
|
+
|
|
9612
9703
|
if constexpr (std::is_destructible_v<T>)
|
|
9613
9704
|
{
|
|
9614
9705
|
if (this->isOwner_)
|
|
@@ -9619,14 +9710,23 @@ namespace Rice::detail
|
|
|
9619
9710
|
}
|
|
9620
9711
|
|
|
9621
9712
|
template <typename T>
|
|
9622
|
-
inline void* Wrapper<T*>::get()
|
|
9713
|
+
inline void* Wrapper<T*>::get(rb_data_type_t* requestedType)
|
|
9623
9714
|
{
|
|
9624
|
-
|
|
9715
|
+
if (rb_typeddata_inherited_p(this->rb_data_type_, requestedType))
|
|
9716
|
+
{
|
|
9717
|
+
return (void*)this->data_;
|
|
9718
|
+
}
|
|
9719
|
+
else
|
|
9720
|
+
{
|
|
9721
|
+
throw Exception(rb_eTypeError, "wrong argument type %s (expected %s)",
|
|
9722
|
+
this->rb_data_type_->wrap_struct_name,
|
|
9723
|
+
requestedType->wrap_struct_name);
|
|
9724
|
+
}
|
|
9625
9725
|
}
|
|
9626
9726
|
|
|
9627
9727
|
// ---- Wrapper** -----
|
|
9628
9728
|
template <typename T>
|
|
9629
|
-
inline Wrapper<T**>::Wrapper(T** data, bool isOwner) : data_(data)
|
|
9729
|
+
inline Wrapper<T**>::Wrapper(rb_data_type_t* rb_data_type, T** data, bool isOwner) : WrapperBase(rb_data_type), data_(data)
|
|
9630
9730
|
{
|
|
9631
9731
|
this->isOwner_ = isOwner;
|
|
9632
9732
|
this->isConst_ = std::is_const_v<std::remove_pointer_t<std::remove_pointer_t<T>>>;
|
|
@@ -9635,7 +9735,8 @@ namespace Rice::detail
|
|
|
9635
9735
|
template <typename T>
|
|
9636
9736
|
inline Wrapper<T**>::~Wrapper()
|
|
9637
9737
|
{
|
|
9638
|
-
Registries::instance.instances.remove(this->get());
|
|
9738
|
+
Registries::instance.instances.remove(this->get(this->rb_data_type_));
|
|
9739
|
+
|
|
9639
9740
|
if constexpr (std::is_destructible_v<T>)
|
|
9640
9741
|
{
|
|
9641
9742
|
if (this->isOwner_)
|
|
@@ -9646,9 +9747,18 @@ namespace Rice::detail
|
|
|
9646
9747
|
}
|
|
9647
9748
|
|
|
9648
9749
|
template <typename T>
|
|
9649
|
-
inline void* Wrapper<T**>::get()
|
|
9750
|
+
inline void* Wrapper<T**>::get(rb_data_type_t* requestedType)
|
|
9650
9751
|
{
|
|
9651
|
-
|
|
9752
|
+
if (rb_typeddata_inherited_p(this->rb_data_type_, requestedType))
|
|
9753
|
+
{
|
|
9754
|
+
return (void*)this->data_;
|
|
9755
|
+
}
|
|
9756
|
+
else
|
|
9757
|
+
{
|
|
9758
|
+
throw Exception(rb_eTypeError, "wrong argument type %s (expected %s)",
|
|
9759
|
+
this->rb_data_type_->wrap_struct_name,
|
|
9760
|
+
requestedType->wrap_struct_name);
|
|
9761
|
+
}
|
|
9652
9762
|
}
|
|
9653
9763
|
|
|
9654
9764
|
// ---- Helper Functions -------
|
|
@@ -9665,7 +9775,7 @@ namespace Rice::detail
|
|
|
9665
9775
|
// If Ruby is not the owner then wrap the reference
|
|
9666
9776
|
if (!isOwner)
|
|
9667
9777
|
{
|
|
9668
|
-
wrapper = new Wrapper<T&>(data);
|
|
9778
|
+
wrapper = new Wrapper<T&>(rb_data_type, data);
|
|
9669
9779
|
result = TypedData_Wrap_Struct(klass, rb_data_type, wrapper);
|
|
9670
9780
|
}
|
|
9671
9781
|
|
|
@@ -9674,12 +9784,12 @@ namespace Rice::detail
|
|
|
9674
9784
|
{
|
|
9675
9785
|
if constexpr (std::is_copy_constructible_v<typename T::value_type>)
|
|
9676
9786
|
{
|
|
9677
|
-
wrapper = new Wrapper<T>(data);
|
|
9787
|
+
wrapper = new Wrapper<T>(rb_data_type, data);
|
|
9678
9788
|
result = TypedData_Wrap_Struct(klass, rb_data_type, wrapper);
|
|
9679
9789
|
}
|
|
9680
9790
|
else
|
|
9681
9791
|
{
|
|
9682
|
-
wrapper = new Wrapper<T>(std::move(data));
|
|
9792
|
+
wrapper = new Wrapper<T>(rb_data_type, std::move(data));
|
|
9683
9793
|
result = TypedData_Wrap_Struct(klass, rb_data_type, wrapper);
|
|
9684
9794
|
}
|
|
9685
9795
|
}
|
|
@@ -9687,14 +9797,14 @@ namespace Rice::detail
|
|
|
9687
9797
|
// Ruby is the owner so copy data
|
|
9688
9798
|
else if constexpr (std::is_copy_constructible_v<T>)
|
|
9689
9799
|
{
|
|
9690
|
-
wrapper = new Wrapper<T>(data);
|
|
9800
|
+
wrapper = new Wrapper<T>(rb_data_type, data);
|
|
9691
9801
|
result = TypedData_Wrap_Struct(klass, rb_data_type, wrapper);
|
|
9692
9802
|
}
|
|
9693
9803
|
|
|
9694
9804
|
// Ruby is the owner so move data
|
|
9695
9805
|
else if constexpr (std::is_move_constructible_v<T>)
|
|
9696
9806
|
{
|
|
9697
|
-
wrapper = new Wrapper<T>(std::move(data));
|
|
9807
|
+
wrapper = new Wrapper<T>(rb_data_type, std::move(data));
|
|
9698
9808
|
result = TypedData_Wrap_Struct(klass, rb_data_type, wrapper);
|
|
9699
9809
|
}
|
|
9700
9810
|
|
|
@@ -9706,7 +9816,7 @@ namespace Rice::detail
|
|
|
9706
9816
|
throw std::runtime_error(message);
|
|
9707
9817
|
}
|
|
9708
9818
|
|
|
9709
|
-
Registries::instance.instances.add(wrapper->get(), result);
|
|
9819
|
+
Registries::instance.instances.add(wrapper->get(rb_data_type), result);
|
|
9710
9820
|
|
|
9711
9821
|
return result;
|
|
9712
9822
|
};
|
|
@@ -9719,38 +9829,40 @@ namespace Rice::detail
|
|
|
9719
9829
|
if (result != Qnil)
|
|
9720
9830
|
return result;
|
|
9721
9831
|
|
|
9722
|
-
WrapperBase* wrapper = new Wrapper<T*>(data, isOwner);
|
|
9832
|
+
WrapperBase* wrapper = new Wrapper<T*>(rb_data_type, data, isOwner);
|
|
9723
9833
|
result = TypedData_Wrap_Struct(klass, rb_data_type, wrapper);
|
|
9724
9834
|
|
|
9725
|
-
Registries::instance.instances.add(wrapper->get(), result);
|
|
9835
|
+
Registries::instance.instances.add(wrapper->get(rb_data_type), result);
|
|
9726
9836
|
return result;
|
|
9727
9837
|
};
|
|
9728
9838
|
|
|
9729
9839
|
template <typename T>
|
|
9730
9840
|
inline T* unwrap(VALUE value, rb_data_type_t* rb_data_type, bool takeOwnership)
|
|
9731
9841
|
{
|
|
9732
|
-
if (
|
|
9842
|
+
if (!RTYPEDDATA_P(value))
|
|
9733
9843
|
{
|
|
9734
9844
|
std::string message = "The Ruby object does not wrap a C++ object. It is actually a " +
|
|
9735
9845
|
std::string(detail::protect(rb_obj_classname, value)) + ".";
|
|
9736
9846
|
throw std::runtime_error(message);
|
|
9737
9847
|
}
|
|
9738
9848
|
|
|
9739
|
-
WrapperBase* wrapper =
|
|
9849
|
+
WrapperBase* wrapper = static_cast<WrapperBase*>(RTYPEDDATA_DATA(value));
|
|
9740
9850
|
|
|
9741
9851
|
if (wrapper == nullptr)
|
|
9742
9852
|
{
|
|
9743
|
-
std::string message = "Wrapped C++ object is nil. Did you override " +
|
|
9744
|
-
std::string(detail::protect(rb_obj_classname, value)) +
|
|
9853
|
+
std::string message = "Wrapped C++ object is nil. Did you override " +
|
|
9854
|
+
std::string(detail::protect(rb_obj_classname, value)) +
|
|
9745
9855
|
"#initialize and forget to call super?";
|
|
9746
9856
|
|
|
9747
9857
|
throw std::runtime_error(message);
|
|
9748
9858
|
}
|
|
9749
9859
|
|
|
9750
9860
|
if (takeOwnership)
|
|
9861
|
+
{
|
|
9751
9862
|
wrapper->setOwner(false);
|
|
9863
|
+
}
|
|
9752
9864
|
|
|
9753
|
-
return static_cast<T*>(wrapper->get());
|
|
9865
|
+
return static_cast<T*>(wrapper->get(rb_data_type));
|
|
9754
9866
|
}
|
|
9755
9867
|
|
|
9756
9868
|
template <typename Wrapper_T>
|
|
@@ -9772,7 +9884,8 @@ namespace Rice::detail
|
|
|
9772
9884
|
if (!RTYPEDDATA_P(value))
|
|
9773
9885
|
{
|
|
9774
9886
|
throw Exception(rb_eTypeError, "wrong argument type %s (expected %s)",
|
|
9775
|
-
|
|
9887
|
+
detail::protect(rb_obj_classname, value),
|
|
9888
|
+
"wrapped C++ object");
|
|
9776
9889
|
}
|
|
9777
9890
|
|
|
9778
9891
|
return static_cast<WrapperBase*>(RTYPEDDATA_DATA(value));
|
|
@@ -9783,24 +9896,26 @@ namespace Rice::detail
|
|
|
9783
9896
|
}
|
|
9784
9897
|
|
|
9785
9898
|
template <typename T>
|
|
9786
|
-
inline
|
|
9899
|
+
inline Wrapper<T*>* wrapConstructed(VALUE value, rb_data_type_t* rb_data_type, T* data)
|
|
9787
9900
|
{
|
|
9788
9901
|
using Wrapper_T = Wrapper<T*>;
|
|
9789
|
-
|
|
9902
|
+
|
|
9790
9903
|
Wrapper_T* wrapper = nullptr;
|
|
9791
9904
|
TypedData_Get_Struct(value, Wrapper_T, rb_data_type, wrapper);
|
|
9792
9905
|
if (wrapper)
|
|
9793
9906
|
{
|
|
9794
|
-
Registries::instance.instances.remove(wrapper->get());
|
|
9907
|
+
Registries::instance.instances.remove(wrapper->get(rb_data_type));
|
|
9795
9908
|
delete wrapper;
|
|
9796
9909
|
}
|
|
9797
9910
|
|
|
9798
|
-
wrapper = new Wrapper_T(data, true);
|
|
9911
|
+
wrapper = new Wrapper_T(rb_data_type, data, true);
|
|
9799
9912
|
RTYPEDDATA_DATA(value) = wrapper;
|
|
9800
9913
|
|
|
9801
9914
|
Registries::instance.instances.add(data, value);
|
|
9915
|
+
|
|
9916
|
+
return wrapper;
|
|
9802
9917
|
}
|
|
9803
|
-
}
|
|
9918
|
+
}
|
|
9804
9919
|
|
|
9805
9920
|
// ========= Native.ipp =========
|
|
9806
9921
|
namespace Rice::detail
|
|
@@ -9981,16 +10096,14 @@ namespace Rice::detail
|
|
|
9981
10096
|
Arg* arg = parameters_[i]->arg();
|
|
9982
10097
|
if (arg->isKeepAlive())
|
|
9983
10098
|
{
|
|
9984
|
-
|
|
9985
|
-
selfWrapper->addKeepAlive(rubyValues[i].value());
|
|
10099
|
+
WrapperBase::addKeepAlive(self, rubyValues[i].value());
|
|
9986
10100
|
}
|
|
9987
10101
|
}
|
|
9988
10102
|
|
|
9989
10103
|
// Check return value
|
|
9990
10104
|
if (this->returnInfo_->isKeepAlive())
|
|
9991
10105
|
{
|
|
9992
|
-
WrapperBase
|
|
9993
|
-
returnWrapper->addKeepAlive(self);
|
|
10106
|
+
WrapperBase::addKeepAlive(returnValue, self);
|
|
9994
10107
|
}
|
|
9995
10108
|
}
|
|
9996
10109
|
|
|
@@ -10329,7 +10442,7 @@ namespace Rice::detail
|
|
|
10329
10442
|
// matches or calls function pointer. Instead Ruby can call the static call method defined on
|
|
10330
10443
|
// this class (&NativeAttribute_T::get).
|
|
10331
10444
|
Identifier identifier(name);
|
|
10332
|
-
detail::Registries::instance.natives.
|
|
10445
|
+
detail::Registries::instance.natives.replace(klass, identifier.id(), native);
|
|
10333
10446
|
}
|
|
10334
10447
|
|
|
10335
10448
|
template<typename Attribute_T>
|
|
@@ -10434,28 +10547,46 @@ namespace Rice::detail
|
|
|
10434
10547
|
namespace Rice::detail
|
|
10435
10548
|
{
|
|
10436
10549
|
template<typename Attribute_T>
|
|
10437
|
-
|
|
10550
|
+
template<typename...Arg_Ts>
|
|
10551
|
+
void NativeAttributeSet<Attribute_T>::define(VALUE klass, std::string name, Attribute_T attribute, Arg_Ts&...args)
|
|
10438
10552
|
{
|
|
10439
|
-
//
|
|
10440
|
-
|
|
10553
|
+
// Extract Arg from Arg_Ts if present, otherwise create default
|
|
10554
|
+
using Arg_Tuple = std::tuple<Arg_Ts...>;
|
|
10555
|
+
constexpr std::size_t index = tuple_element_index_v<Arg_Tuple, Arg, ArgBuffer>;
|
|
10556
|
+
|
|
10557
|
+
std::unique_ptr<Arg> arg;
|
|
10558
|
+
if constexpr (index < std::tuple_size_v<Arg_Tuple>)
|
|
10559
|
+
{
|
|
10560
|
+
using Arg_T_Local = std::decay_t<std::tuple_element_t<index, Arg_Tuple>>;
|
|
10561
|
+
const Arg_T_Local& argInfo = std::get<index>(std::forward_as_tuple(std::forward<Arg_Ts>(args)...));
|
|
10562
|
+
arg = std::make_unique<Arg_T_Local>(argInfo);
|
|
10563
|
+
}
|
|
10564
|
+
else
|
|
10565
|
+
{
|
|
10566
|
+
arg = std::make_unique<Arg>("value");
|
|
10567
|
+
}
|
|
10568
|
+
|
|
10569
|
+
// Create the parameter
|
|
10570
|
+
auto parameter = std::make_unique<Parameter<T_Unqualified>>(std::move(arg));
|
|
10571
|
+
|
|
10572
|
+
// Create a NativeAttributeSet that Ruby will call to write C++ variables
|
|
10573
|
+
NativeAttribute_T* nativeAttribute = new NativeAttribute_T(klass, name, std::forward<Attribute_T>(attribute), std::move(parameter));
|
|
10441
10574
|
std::unique_ptr<Native> native(nativeAttribute);
|
|
10442
10575
|
|
|
10443
10576
|
// Define the write method name
|
|
10444
10577
|
std::string setter = name + "=";
|
|
10445
10578
|
|
|
10446
|
-
// Tell Ruby to invoke the static method
|
|
10579
|
+
// Tell Ruby to invoke the static method resolve to set the attribute value
|
|
10447
10580
|
detail::protect(rb_define_method, klass, setter.c_str(), (RUBY_METHOD_FUNC)&Native::resolve, -1);
|
|
10448
10581
|
|
|
10449
|
-
// Add to native registry
|
|
10450
|
-
// matches or calls function pointer. Instead Ruby can call the static call method defined on
|
|
10451
|
-
// this class (&NativeAttribute_T::set).
|
|
10582
|
+
// Add to native registry
|
|
10452
10583
|
Identifier identifier(setter);
|
|
10453
|
-
detail::Registries::instance.natives.
|
|
10584
|
+
detail::Registries::instance.natives.replace(klass, identifier.id(), native);
|
|
10454
10585
|
}
|
|
10455
10586
|
|
|
10456
10587
|
template<typename Attribute_T>
|
|
10457
|
-
NativeAttributeSet<Attribute_T>::NativeAttributeSet(VALUE klass, std::string name, Attribute_T attribute)
|
|
10458
|
-
: Native(name), klass_(klass), attribute_(attribute)
|
|
10588
|
+
NativeAttributeSet<Attribute_T>::NativeAttributeSet(VALUE klass, std::string name, Attribute_T attribute, std::unique_ptr<Parameter<T_Unqualified>> parameter)
|
|
10589
|
+
: Native(name), klass_(klass), attribute_(attribute), parameter_(std::move(parameter))
|
|
10459
10590
|
{
|
|
10460
10591
|
}
|
|
10461
10592
|
|
|
@@ -10476,25 +10607,25 @@ namespace Rice::detail
|
|
|
10476
10607
|
throw std::runtime_error("Incorrect number of parameters for setting attribute. Attribute: " + this->name_);
|
|
10477
10608
|
}
|
|
10478
10609
|
|
|
10610
|
+
// Get the Ruby value and convert to native
|
|
10479
10611
|
VALUE value = values.begin()->second;
|
|
10612
|
+
std::optional<VALUE> valueOpt(value);
|
|
10613
|
+
T_Unqualified nativeValue = this->parameter_->convertToNative(valueOpt);
|
|
10480
10614
|
|
|
10481
10615
|
if constexpr (!std::is_null_pointer_v<Receiver_T>)
|
|
10482
10616
|
{
|
|
10483
10617
|
Receiver_T* nativeSelf = From_Ruby<Receiver_T*>().convert(self);
|
|
10484
|
-
|
|
10485
|
-
// Deal with pointers to pointes, see Parameter::convertToNative commment
|
|
10486
|
-
if constexpr (is_pointer_pointer_v<Attr_T> && !std::is_convertible_v<remove_cv_recursive_t<Attr_T>, Attr_T>)
|
|
10487
|
-
{
|
|
10488
|
-
nativeSelf->*attribute_ = (Attr_T)From_Ruby<T_Unqualified>().convert(value);
|
|
10489
|
-
}
|
|
10490
|
-
else
|
|
10491
|
-
{
|
|
10492
|
-
nativeSelf->*attribute_ = From_Ruby<T_Unqualified>().convert(value);
|
|
10493
|
-
}
|
|
10618
|
+
nativeSelf->*attribute_ = (Attr_T)nativeValue;
|
|
10494
10619
|
}
|
|
10495
10620
|
else
|
|
10496
10621
|
{
|
|
10497
|
-
*attribute_ =
|
|
10622
|
+
*attribute_ = nativeValue;
|
|
10623
|
+
}
|
|
10624
|
+
|
|
10625
|
+
// Check if we need to prevent the value from being garbage collected
|
|
10626
|
+
if (this->parameter_->arg()->isKeepAlive())
|
|
10627
|
+
{
|
|
10628
|
+
WrapperBase::addKeepAlive(self, value);
|
|
10498
10629
|
}
|
|
10499
10630
|
|
|
10500
10631
|
return value;
|
|
@@ -10515,18 +10646,8 @@ namespace Rice::detail
|
|
|
10515
10646
|
template<typename Attribute_T>
|
|
10516
10647
|
inline VALUE NativeAttributeSet<Attribute_T>::returnKlass()
|
|
10517
10648
|
{
|
|
10518
|
-
|
|
10519
|
-
|
|
10520
|
-
if (isBuffer)
|
|
10521
|
-
{
|
|
10522
|
-
TypeMapper<Pointer<detail::remove_cv_recursive_t<std::remove_pointer_t<Attr_T>>>> typeMapper;
|
|
10523
|
-
return typeMapper.rubyKlass();
|
|
10524
|
-
}
|
|
10525
|
-
else
|
|
10526
|
-
{
|
|
10527
|
-
TypeMapper<Attr_T> typeMapper;
|
|
10528
|
-
return typeMapper.rubyKlass();
|
|
10529
|
-
}
|
|
10649
|
+
TypeMapper<Attr_T> typeMapper;
|
|
10650
|
+
return typeMapper.rubyKlass();
|
|
10530
10651
|
}
|
|
10531
10652
|
}
|
|
10532
10653
|
|
|
@@ -11166,30 +11287,33 @@ namespace Rice::detail
|
|
|
11166
11287
|
{
|
|
11167
11288
|
return self;
|
|
11168
11289
|
}
|
|
11169
|
-
/* This case happens when a class wrapped by Rice is calling a method
|
|
11170
|
-
defined on an ancestor class. For example, the std::map size method
|
|
11171
|
-
is defined on _Tree not map. Rice needs to know the actual type
|
|
11172
|
-
that was wrapped so it can correctly extract the C++ object from
|
|
11173
|
-
the Ruby object. */
|
|
11174
|
-
else if constexpr (!std::is_same_v<intrinsic_type<Receiver_T>, Class_T> &&
|
|
11175
|
-
std::is_base_of_v<intrinsic_type<Receiver_T>, Class_T> &&
|
|
11176
|
-
std::is_pointer_v<Receiver_T>)
|
|
11177
|
-
{
|
|
11178
|
-
Class_T* instance = From_Ruby<Class_T*>().convert(self);
|
|
11179
|
-
return dynamic_cast<Receiver_T>(instance);
|
|
11180
|
-
}
|
|
11181
|
-
else if constexpr (!std::is_same_v<intrinsic_type<Receiver_T>, Class_T> &&
|
|
11182
|
-
std::is_base_of_v<intrinsic_type<Receiver_T>, Class_T> &&
|
|
11183
|
-
std::is_reference_v<Receiver_T>)
|
|
11184
|
-
{
|
|
11185
|
-
Class_T& instance = From_Ruby<Class_T&>().convert(self);
|
|
11186
|
-
return dynamic_cast<Receiver_T>(instance);
|
|
11187
|
-
}
|
|
11188
|
-
// Self parameter could be derived from Object or it is an C++ instance and
|
|
11189
|
-
// needs to be unwrapped from Ruby
|
|
11190
11290
|
else
|
|
11191
11291
|
{
|
|
11192
|
-
|
|
11292
|
+
/* When a class wrapped by Rice calls a method defined on an ancestor class
|
|
11293
|
+
(e.g., std::map calling a method from _Tree), we need to unwrap as Class_T
|
|
11294
|
+
and dynamic_cast to the base class. Otherwise unwrap directly as Receiver_T. */
|
|
11295
|
+
constexpr bool isDerived = !std::is_same_v<intrinsic_type<Receiver_T>, Class_T> &&
|
|
11296
|
+
std::is_base_of_v<intrinsic_type<Receiver_T>, Class_T>;
|
|
11297
|
+
|
|
11298
|
+
if constexpr (isDerived)
|
|
11299
|
+
{
|
|
11300
|
+
if constexpr (std::is_pointer_v<Receiver_T>)
|
|
11301
|
+
{
|
|
11302
|
+
Class_T* instance = From_Ruby<Class_T*>().convert(self);
|
|
11303
|
+
return dynamic_cast<Receiver_T>(instance);
|
|
11304
|
+
}
|
|
11305
|
+
else if constexpr (std::is_reference_v<Receiver_T>)
|
|
11306
|
+
{
|
|
11307
|
+
Class_T& instance = From_Ruby<Class_T&>().convert(self);
|
|
11308
|
+
return dynamic_cast<Receiver_T>(instance);
|
|
11309
|
+
}
|
|
11310
|
+
}
|
|
11311
|
+
else
|
|
11312
|
+
{
|
|
11313
|
+
// Note GCC has a false warning: function may return address of local variable [-Wreturn-local-addr].
|
|
11314
|
+
// From_Ruby returns a reference to data in the Ruby object, not the temporary.
|
|
11315
|
+
return From_Ruby<Receiver_T>().convert(self);
|
|
11316
|
+
}
|
|
11193
11317
|
}
|
|
11194
11318
|
}
|
|
11195
11319
|
|
|
@@ -12119,6 +12243,11 @@ namespace Rice
|
|
|
12119
12243
|
return RB_TEST(result);
|
|
12120
12244
|
}
|
|
12121
12245
|
|
|
12246
|
+
inline void Object::extend(Module const& mod)
|
|
12247
|
+
{
|
|
12248
|
+
detail::protect(rb_extend_object, this->value(), mod.value());
|
|
12249
|
+
}
|
|
12250
|
+
|
|
12122
12251
|
inline bool Object::respond_to(Identifier id) const
|
|
12123
12252
|
{
|
|
12124
12253
|
return bool(rb_respond_to(this->value(), id.id()));
|
|
@@ -13513,6 +13642,11 @@ namespace Rice
|
|
|
13513
13642
|
return result;
|
|
13514
13643
|
}
|
|
13515
13644
|
|
|
13645
|
+
inline Class Class::superclass() const
|
|
13646
|
+
{
|
|
13647
|
+
return detail::protect(rb_class_superclass, this->value());
|
|
13648
|
+
}
|
|
13649
|
+
|
|
13516
13650
|
inline Class define_class_under(Object parent, Identifier id, const Class& superclass)
|
|
13517
13651
|
{
|
|
13518
13652
|
VALUE klass = detail::protect(rb_define_class_id_under, parent.value(), id, superclass.value());
|
|
@@ -14067,17 +14201,22 @@ namespace Rice
|
|
|
14067
14201
|
template<typename T>
|
|
14068
14202
|
inline void ruby_mark_internal(detail::WrapperBase* wrapper)
|
|
14069
14203
|
{
|
|
14070
|
-
|
|
14071
|
-
|
|
14204
|
+
detail::cpp_protect([&]
|
|
14205
|
+
{
|
|
14206
|
+
// Tell the wrapper to mark the objects its keeping alive
|
|
14207
|
+
wrapper->ruby_mark();
|
|
14072
14208
|
|
|
14073
|
-
|
|
14074
|
-
|
|
14075
|
-
|
|
14209
|
+
// Get the underlying data and call custom mark function (if any)
|
|
14210
|
+
// Use the wrapper's stored rb_data_type to avoid type mismatch
|
|
14211
|
+
T* data = static_cast<T*>(wrapper->get(Data_Type<T>::ruby_data_type()));
|
|
14212
|
+
ruby_mark<T>(data);
|
|
14213
|
+
});
|
|
14076
14214
|
}
|
|
14077
14215
|
|
|
14078
14216
|
template<typename T>
|
|
14079
14217
|
inline void ruby_free_internal(detail::WrapperBase* wrapper)
|
|
14080
14218
|
{
|
|
14219
|
+
// Destructors are noexcept so we cannot use cpp_protect here
|
|
14081
14220
|
delete wrapper;
|
|
14082
14221
|
}
|
|
14083
14222
|
|
|
@@ -14442,7 +14581,7 @@ namespace Rice
|
|
|
14442
14581
|
}
|
|
14443
14582
|
else
|
|
14444
14583
|
{
|
|
14445
|
-
detail::NativeAttributeSet<Attribute_T>::define(klass, name, std::forward<Attribute_T>(attribute));
|
|
14584
|
+
detail::NativeAttributeSet<Attribute_T>::define(klass, name, std::forward<Attribute_T>(attribute), args...);
|
|
14446
14585
|
}
|
|
14447
14586
|
}
|
|
14448
14587
|
|
|
@@ -15662,6 +15801,86 @@ namespace Rice
|
|
|
15662
15801
|
}
|
|
15663
15802
|
}
|
|
15664
15803
|
|
|
15804
|
+
// Dependent on Module, Array, Symbol - used by stl smart pointers
|
|
15805
|
+
|
|
15806
|
+
// ========= Forwards.hpp =========
|
|
15807
|
+
|
|
15808
|
+
namespace Rice::detail
|
|
15809
|
+
{
|
|
15810
|
+
// Setup method forwarding from a wrapper class to its wrapped type using Ruby's Forwardable.
|
|
15811
|
+
// This allows calling methods on the wrapper that get delegated to the wrapped object via
|
|
15812
|
+
// a "get" method that returns the wrapped object.
|
|
15813
|
+
//
|
|
15814
|
+
// Parameters:
|
|
15815
|
+
// wrapper_klass - The Ruby class to add forwarding to (e.g., SharedPtr_MyClass)
|
|
15816
|
+
// wrapped_klass - The Ruby class whose methods should be forwarded (e.g., MyClass)
|
|
15817
|
+
void define_forwarding(VALUE wrapper_klass, VALUE wrapped_klass);
|
|
15818
|
+
}
|
|
15819
|
+
|
|
15820
|
+
|
|
15821
|
+
// --------- Forwards.ipp ---------
|
|
15822
|
+
namespace Rice::detail
|
|
15823
|
+
{
|
|
15824
|
+
inline void define_forwarding(VALUE wrapper_klass, VALUE wrapped_klass)
|
|
15825
|
+
{
|
|
15826
|
+
protect(rb_require, "forwardable");
|
|
15827
|
+
Object forwardable = Object(rb_cObject).const_get("Forwardable");
|
|
15828
|
+
Object(wrapper_klass).extend(forwardable.value());
|
|
15829
|
+
|
|
15830
|
+
// Get wrapper class's method names to avoid conflicts
|
|
15831
|
+
std::set<std::string> wrapperMethodSet;
|
|
15832
|
+
for (Native* native : Registries::instance.natives.lookup(wrapper_klass, NativeKind::Method))
|
|
15833
|
+
{
|
|
15834
|
+
wrapperMethodSet.insert(native->name());
|
|
15835
|
+
}
|
|
15836
|
+
for (Native* native : Registries::instance.natives.lookup(wrapper_klass, NativeKind::AttributeReader))
|
|
15837
|
+
{
|
|
15838
|
+
wrapperMethodSet.insert(native->name());
|
|
15839
|
+
}
|
|
15840
|
+
for (Native* native : Registries::instance.natives.lookup(wrapper_klass, NativeKind::AttributeWriter))
|
|
15841
|
+
{
|
|
15842
|
+
wrapperMethodSet.insert(native->name() + "=");
|
|
15843
|
+
}
|
|
15844
|
+
|
|
15845
|
+
// Get wrapped class's method names from the registry, including ancestor classes
|
|
15846
|
+
std::set<std::string> wrappedMethodSet;
|
|
15847
|
+
Class klass(wrapped_klass);
|
|
15848
|
+
while (klass.value() != rb_cObject && klass.value() != Qnil)
|
|
15849
|
+
{
|
|
15850
|
+
for (Native* native : Registries::instance.natives.lookup(klass.value(), NativeKind::Method))
|
|
15851
|
+
{
|
|
15852
|
+
wrappedMethodSet.insert(native->name());
|
|
15853
|
+
}
|
|
15854
|
+
for (Native* native : Registries::instance.natives.lookup(klass.value(), NativeKind::AttributeReader))
|
|
15855
|
+
{
|
|
15856
|
+
wrappedMethodSet.insert(native->name());
|
|
15857
|
+
}
|
|
15858
|
+
for (Native* native : Registries::instance.natives.lookup(klass.value(), NativeKind::AttributeWriter))
|
|
15859
|
+
{
|
|
15860
|
+
wrappedMethodSet.insert(native->name() + "=");
|
|
15861
|
+
}
|
|
15862
|
+
|
|
15863
|
+
klass = klass.superclass();
|
|
15864
|
+
}
|
|
15865
|
+
|
|
15866
|
+
// Build the arguments array for def_delegators: [:get, :method1, :method2, ...]
|
|
15867
|
+
// Skip methods that are already defined on the wrapper class
|
|
15868
|
+
Array args;
|
|
15869
|
+
args.push(Symbol("get"));
|
|
15870
|
+
for (const std::string& method : wrappedMethodSet)
|
|
15871
|
+
{
|
|
15872
|
+
if (wrapperMethodSet.find(method) == wrapperMethodSet.end())
|
|
15873
|
+
{
|
|
15874
|
+
args.push(Symbol(method));
|
|
15875
|
+
}
|
|
15876
|
+
}
|
|
15877
|
+
|
|
15878
|
+
// Call def_delegators(*args)
|
|
15879
|
+
Object(wrapper_klass).vcall("def_delegators", args);
|
|
15880
|
+
}
|
|
15881
|
+
}
|
|
15882
|
+
|
|
15883
|
+
|
|
15665
15884
|
// For now include libc support - maybe should be separate header file someday
|
|
15666
15885
|
|
|
15667
15886
|
// ========= file.hpp =========
|