rice 4.8.0 → 4.9.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 +8 -0
- data/bin/rice-doc.rb +2 -0
- data/include/rice/api.hpp +14 -1
- data/include/rice/rice.hpp +237 -51
- data/include/rice/stl.hpp +166 -165
- data/lib/rice/doc/rice.rb +2 -1
- data/lib/rice/native_registry.rb +4 -9
- data/lib/rice/rbs.rb +4 -4
- data/lib/rice/version.rb +1 -1
- data/rice/Data_Type.ipp +11 -6
- 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/NativeRegistry.hpp +1 -0
- data/rice/detail/NativeRegistry.ipp +29 -0
- data/rice/detail/Type.ipp +4 -0
- data/rice/detail/Wrapper.hpp +12 -11
- data/rice/detail/Wrapper.ipp +80 -35
- data/rice/rice.hpp +3 -0
- data/rice/rice_api/NativeRegistry.ipp +14 -1
- data/rice/stl/shared_ptr.hpp +16 -0
- data/rice/stl/shared_ptr.ipp +61 -38
- data/rice/stl/unique_ptr.hpp +9 -3
- data/rice/stl/unique_ptr.ipp +80 -124
- data/test/test_Inheritance.cpp +14 -14
- data/test/test_Keep_Alive_No_Wrapper.cpp +6 -2
- data/test/test_Stl_SharedPtr.cpp +160 -45
- data/test/test_Stl_UniquePtr.cpp +48 -3
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 60ee7533ef1a2e8fae4a992ef2d1dc2f3dd1cd4ab260217058e9de77ead8f80b
|
|
4
|
+
data.tar.gz: 83393a7a4238d817da51eccc5392d318bb2dab00e57d9ce688867a748a50f7a5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 26c796a5fcac6d816f9cddda0944be07a16cc93a0264221a351f4612061ed3b0e61dd4ab99eae0470ebc62e483f762820116024f6814f9f0023adccc466d66cf
|
|
7
|
+
data.tar.gz: aacb86cb9d086100650839ac2cf2cf49d60dcf4604f3539be24e0922c3f3ca3a8f06dfb0511e1e1b3281e9f475cf621218ac165b4c155e5d6e4e2083b3444823
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 4.9.0 (2026-01-01)
|
|
4
|
+
This release revamps smart pointer support for `std::shared_ptr` and `std::unique_ptr`.
|
|
5
|
+
|
|
6
|
+
Rice now always creates wrapper classes for smart pointers under the `Std` module (e.g., `Std::SharedPtr≺MyClass≻`, `Std::UniquePtr≺MyClass≻`). These wrapper classes expose methods like `empty?`, `get`, `swap`, and for shared_ptr, `use_count`. Methods defined on the managed type are automatically forwarded to the wrapper class using Ruby's `Forwardable` module.
|
|
7
|
+
|
|
8
|
+
This change is backwards compatible for Ruby code but not C++ code. If you have implemented your own Smart Pointer wrapper then please read the Smart Pointer documentation for more information on how to update it.
|
|
9
|
+
|
|
3
10
|
## 4.8.0 (2025-12-29)
|
|
4
11
|
This release focuses on making Rice easier to use:
|
|
5
12
|
|
|
@@ -25,6 +32,7 @@ However, these changes did require some breaking changes, which include:
|
|
|
25
32
|
* `Arg("").isBuffer()` is replaced by `ArgBuffer("")`
|
|
26
33
|
* `Function().noGVL()` is replaced by `NoGvL()`
|
|
27
34
|
* `is_convertible` methods must now return a `double` instead of a `Convertible` enum
|
|
35
|
+
* All function/method parameter default values are verified. You may see errors like "ArgumentError: Type is not registered with Rice" or "Invalid AnyCast". In either case, make sure to check that specified default values are correct.
|
|
28
36
|
|
|
29
37
|
## 4.7.1 (2025-10-28)
|
|
30
38
|
Updates:
|
data/bin/rice-doc.rb
CHANGED
|
@@ -114,6 +114,8 @@ unless Dir.exist?(config.output)
|
|
|
114
114
|
FileUtils.mkdir_p(config.output)
|
|
115
115
|
end
|
|
116
116
|
|
|
117
|
+
# Add the extension directory the path in case it ships with extra libraries
|
|
118
|
+
ENV["PATH"] = "#{File.dirname(config.extension)}#{File::PATH_SEPARATOR}#{ENV["PATH"]}"
|
|
117
119
|
# Load the extension
|
|
118
120
|
require config.extension
|
|
119
121
|
|
data/include/rice/api.hpp
CHANGED
|
@@ -79,7 +79,20 @@ inline void Init_Native_Registry()
|
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
return result;
|
|
82
|
-
}, Arg("klass").setValue())
|
|
82
|
+
}, Arg("klass").setValue()).
|
|
83
|
+
|
|
84
|
+
define_method("lookup_by_kind", [](detail::NativeRegistry& self, VALUE klass, detail::NativeKind kind) -> Array
|
|
85
|
+
{
|
|
86
|
+
Array result;
|
|
87
|
+
|
|
88
|
+
const std::vector<detail::Native*> natives = self.lookup(klass, kind);
|
|
89
|
+
for (detail::Native* native : natives)
|
|
90
|
+
{
|
|
91
|
+
result.push(native, false);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return result;
|
|
95
|
+
}, Arg("klass").setValue(), Arg("kind"));
|
|
83
96
|
}
|
|
84
97
|
|
|
85
98
|
// ========= TypeRegistry.hpp =========
|
data/include/rice/rice.hpp
CHANGED
|
@@ -600,9 +600,9 @@ namespace Rice::detail
|
|
|
600
600
|
class WrapperBase
|
|
601
601
|
{
|
|
602
602
|
public:
|
|
603
|
-
WrapperBase()
|
|
603
|
+
WrapperBase(rb_data_type_t* rb_data_type);
|
|
604
604
|
virtual ~WrapperBase() = default;
|
|
605
|
-
virtual void* get() = 0;
|
|
605
|
+
virtual void* get(rb_data_type_t* requestedType) = 0;
|
|
606
606
|
bool isConst();
|
|
607
607
|
|
|
608
608
|
void ruby_mark();
|
|
@@ -610,6 +610,7 @@ namespace Rice::detail
|
|
|
610
610
|
void setOwner(bool value);
|
|
611
611
|
|
|
612
612
|
protected:
|
|
613
|
+
rb_data_type_t* rb_data_type_;
|
|
613
614
|
bool isOwner_ = false;
|
|
614
615
|
bool isConst_ = false;
|
|
615
616
|
|
|
@@ -624,10 +625,10 @@ namespace Rice::detail
|
|
|
624
625
|
class Wrapper : public WrapperBase
|
|
625
626
|
{
|
|
626
627
|
public:
|
|
627
|
-
Wrapper(T& data);
|
|
628
|
-
Wrapper(T&& data);
|
|
628
|
+
Wrapper(rb_data_type_t* rb_data_type, T& data);
|
|
629
|
+
Wrapper(rb_data_type_t* rb_data_type, T&& data);
|
|
629
630
|
~Wrapper();
|
|
630
|
-
void* get() override;
|
|
631
|
+
void* get(rb_data_type_t* requestedType) override;
|
|
631
632
|
|
|
632
633
|
private:
|
|
633
634
|
T data_;
|
|
@@ -637,9 +638,9 @@ namespace Rice::detail
|
|
|
637
638
|
class Wrapper<T&> : public WrapperBase
|
|
638
639
|
{
|
|
639
640
|
public:
|
|
640
|
-
Wrapper(T& data);
|
|
641
|
+
Wrapper(rb_data_type_t* rb_data_type, T& data);
|
|
641
642
|
~Wrapper();
|
|
642
|
-
void* get() override;
|
|
643
|
+
void* get(rb_data_type_t* requestedType) override;
|
|
643
644
|
|
|
644
645
|
private:
|
|
645
646
|
T& data_;
|
|
@@ -649,9 +650,9 @@ namespace Rice::detail
|
|
|
649
650
|
class Wrapper<T*> : public WrapperBase
|
|
650
651
|
{
|
|
651
652
|
public:
|
|
652
|
-
Wrapper(T* data, bool isOwner);
|
|
653
|
+
Wrapper(rb_data_type_t* rb_data_type, T* data, bool isOwner);
|
|
653
654
|
~Wrapper();
|
|
654
|
-
void* get() override;
|
|
655
|
+
void* get(rb_data_type_t* requestedType) override;
|
|
655
656
|
|
|
656
657
|
private:
|
|
657
658
|
T* data_ = nullptr;
|
|
@@ -661,9 +662,9 @@ namespace Rice::detail
|
|
|
661
662
|
class Wrapper<T**> : public WrapperBase
|
|
662
663
|
{
|
|
663
664
|
public:
|
|
664
|
-
Wrapper(T** data, bool isOwner);
|
|
665
|
+
Wrapper(rb_data_type_t* rb_data_type, T** data, bool isOwner);
|
|
665
666
|
~Wrapper();
|
|
666
|
-
void* get() override;
|
|
667
|
+
void* get(rb_data_type_t* requestedType) override;
|
|
667
668
|
|
|
668
669
|
private:
|
|
669
670
|
T** data_ = nullptr;
|
|
@@ -1609,6 +1610,7 @@ namespace Rice
|
|
|
1609
1610
|
namespace Rice
|
|
1610
1611
|
{
|
|
1611
1612
|
class Class;
|
|
1613
|
+
class Module;
|
|
1612
1614
|
class String;
|
|
1613
1615
|
class Array;
|
|
1614
1616
|
|
|
@@ -1716,6 +1718,11 @@ namespace Rice
|
|
|
1716
1718
|
*/
|
|
1717
1719
|
bool is_a(Object klass) const;
|
|
1718
1720
|
|
|
1721
|
+
//! Extend the object with a module.
|
|
1722
|
+
/*! \param mod the module to extend with.
|
|
1723
|
+
*/
|
|
1724
|
+
void extend(Module const& mod);
|
|
1725
|
+
|
|
1719
1726
|
//! Determine if the objects responds to a method.
|
|
1720
1727
|
/*! \param id the name of the method
|
|
1721
1728
|
* \return true if the objects responds to the method, false
|
|
@@ -2697,6 +2704,11 @@ namespace Rice
|
|
|
2697
2704
|
*/
|
|
2698
2705
|
const std::string base_name() const;
|
|
2699
2706
|
|
|
2707
|
+
//! Return the superclass of this class
|
|
2708
|
+
/*! \return Class.
|
|
2709
|
+
*/
|
|
2710
|
+
Class superclass() const;
|
|
2711
|
+
|
|
2700
2712
|
// Include these methods to call methods from Module but return
|
|
2701
2713
|
// an instance of the current classes. This is an alternative to
|
|
2702
2714
|
// using CRTP.
|
|
@@ -3796,6 +3808,7 @@ namespace Rice::detail
|
|
|
3796
3808
|
|
|
3797
3809
|
const std::vector<Native*> lookup(VALUE klass);
|
|
3798
3810
|
const std::vector<std::unique_ptr<Native>>& lookup(VALUE klass, ID methodId);
|
|
3811
|
+
std::vector<Native*> lookup(VALUE klass, NativeKind kind);
|
|
3799
3812
|
|
|
3800
3813
|
private:
|
|
3801
3814
|
// Key - Ruby klass/method
|
|
@@ -8985,6 +8998,35 @@ namespace Rice::detail
|
|
|
8985
8998
|
// Lookup items for method
|
|
8986
8999
|
return this->natives_[key];
|
|
8987
9000
|
}
|
|
9001
|
+
|
|
9002
|
+
inline std::vector<Native*> NativeRegistry::lookup(VALUE klass, NativeKind kind)
|
|
9003
|
+
{
|
|
9004
|
+
std::vector<Native*> result;
|
|
9005
|
+
|
|
9006
|
+
if (rb_type(klass) == T_ICLASS)
|
|
9007
|
+
{
|
|
9008
|
+
klass = detail::protect(rb_class_of, klass);
|
|
9009
|
+
}
|
|
9010
|
+
|
|
9011
|
+
for (auto& pair : this->natives_)
|
|
9012
|
+
{
|
|
9013
|
+
const std::pair<VALUE, ID>& key = pair.first;
|
|
9014
|
+
|
|
9015
|
+
if (klass == key.first)
|
|
9016
|
+
{
|
|
9017
|
+
const std::vector<std::unique_ptr<Native>>& natives = pair.second;
|
|
9018
|
+
for (auto& native : natives)
|
|
9019
|
+
{
|
|
9020
|
+
if (native->kind() == kind)
|
|
9021
|
+
{
|
|
9022
|
+
result.push_back(native.get());
|
|
9023
|
+
}
|
|
9024
|
+
}
|
|
9025
|
+
}
|
|
9026
|
+
}
|
|
9027
|
+
|
|
9028
|
+
return result;
|
|
9029
|
+
}
|
|
8988
9030
|
}
|
|
8989
9031
|
|
|
8990
9032
|
// ========= Registries.ipp =========
|
|
@@ -9207,6 +9249,10 @@ namespace Rice::detail
|
|
|
9207
9249
|
std::regex equalRegex(R"(,\s*std::equal_to)");
|
|
9208
9250
|
removeGroup(base, equalRegex);
|
|
9209
9251
|
|
|
9252
|
+
// Remove default_delete (std::unique_ptr)
|
|
9253
|
+
std::regex defaultDeleteRegex(R"(,\s*std::default_delete)");
|
|
9254
|
+
removeGroup(base, defaultDeleteRegex);
|
|
9255
|
+
|
|
9210
9256
|
// Remove spaces before pointers
|
|
9211
9257
|
std::regex ptrRegex = std::regex(R"(\s+\*)");
|
|
9212
9258
|
base = std::regex_replace(base, ptrRegex, "*");
|
|
@@ -9531,6 +9577,10 @@ namespace Rice::detail
|
|
|
9531
9577
|
|
|
9532
9578
|
namespace Rice::detail
|
|
9533
9579
|
{
|
|
9580
|
+
inline WrapperBase::WrapperBase(rb_data_type_t* rb_data_type) : rb_data_type_(rb_data_type)
|
|
9581
|
+
{
|
|
9582
|
+
}
|
|
9583
|
+
|
|
9534
9584
|
inline bool WrapperBase::isConst()
|
|
9535
9585
|
{
|
|
9536
9586
|
return this->isConst_;
|
|
@@ -9556,31 +9606,40 @@ namespace Rice::detail
|
|
|
9556
9606
|
|
|
9557
9607
|
// ---- Wrapper -----
|
|
9558
9608
|
template <typename T>
|
|
9559
|
-
inline Wrapper<T>::Wrapper(T& data): data_(data)
|
|
9609
|
+
inline Wrapper<T>::Wrapper(rb_data_type_t* rb_data_type, T& data) : WrapperBase(rb_data_type), data_(data)
|
|
9560
9610
|
{
|
|
9561
9611
|
this->isConst_ = std::is_const_v<std::remove_reference_t<T>>;
|
|
9562
9612
|
}
|
|
9563
9613
|
|
|
9564
9614
|
template <typename T>
|
|
9565
|
-
inline Wrapper<T>::Wrapper(T&& data) : data_(std::move(data))
|
|
9615
|
+
inline Wrapper<T>::Wrapper(rb_data_type_t* rb_data_type, T&& data) : WrapperBase(rb_data_type), data_(std::move(data))
|
|
9566
9616
|
{
|
|
9567
9617
|
}
|
|
9568
9618
|
|
|
9569
9619
|
template <typename T>
|
|
9570
9620
|
inline Wrapper<T>::~Wrapper()
|
|
9571
9621
|
{
|
|
9572
|
-
Registries::instance.instances.remove(this->get());
|
|
9622
|
+
Registries::instance.instances.remove(this->get(this->rb_data_type_));
|
|
9573
9623
|
}
|
|
9574
9624
|
|
|
9575
9625
|
template <typename T>
|
|
9576
|
-
inline void* Wrapper<T>::
|
|
9626
|
+
inline void* Wrapper<T>::get(rb_data_type_t* requestedType)
|
|
9577
9627
|
{
|
|
9578
|
-
|
|
9628
|
+
if (rb_typeddata_inherited_p(this->rb_data_type_, requestedType))
|
|
9629
|
+
{
|
|
9630
|
+
return (void*)&this->data_;
|
|
9631
|
+
}
|
|
9632
|
+
else
|
|
9633
|
+
{
|
|
9634
|
+
throw Exception(rb_eTypeError, "wrong argument type %s (expected %s)",
|
|
9635
|
+
this->rb_data_type_->wrap_struct_name,
|
|
9636
|
+
requestedType->wrap_struct_name);
|
|
9637
|
+
}
|
|
9579
9638
|
}
|
|
9580
9639
|
|
|
9581
9640
|
// ---- Wrapper& -----
|
|
9582
9641
|
template <typename T>
|
|
9583
|
-
inline Wrapper<T&>::Wrapper(T& data): data_(data)
|
|
9642
|
+
inline Wrapper<T&>::Wrapper(rb_data_type_t* rb_data_type, T& data) : WrapperBase(rb_data_type), data_(data)
|
|
9584
9643
|
{
|
|
9585
9644
|
this->isConst_ = std::is_const_v<std::remove_reference_t<T>>;
|
|
9586
9645
|
}
|
|
@@ -9588,18 +9647,27 @@ namespace Rice::detail
|
|
|
9588
9647
|
template <typename T>
|
|
9589
9648
|
inline Wrapper<T&>::~Wrapper()
|
|
9590
9649
|
{
|
|
9591
|
-
Registries::instance.instances.remove(this->get());
|
|
9650
|
+
Registries::instance.instances.remove(this->get(this->rb_data_type_));
|
|
9592
9651
|
}
|
|
9593
9652
|
|
|
9594
9653
|
template <typename T>
|
|
9595
|
-
inline void* Wrapper<T&>::get()
|
|
9654
|
+
inline void* Wrapper<T&>::get(rb_data_type_t* requestedType)
|
|
9596
9655
|
{
|
|
9597
|
-
|
|
9656
|
+
if (rb_typeddata_inherited_p(this->rb_data_type_, requestedType))
|
|
9657
|
+
{
|
|
9658
|
+
return (void*)&this->data_;
|
|
9659
|
+
}
|
|
9660
|
+
else
|
|
9661
|
+
{
|
|
9662
|
+
throw Exception(rb_eTypeError, "wrong argument type %s (expected %s)",
|
|
9663
|
+
this->rb_data_type_->wrap_struct_name,
|
|
9664
|
+
requestedType->wrap_struct_name);
|
|
9665
|
+
}
|
|
9598
9666
|
}
|
|
9599
9667
|
|
|
9600
9668
|
// ---- Wrapper* -----
|
|
9601
9669
|
template <typename T>
|
|
9602
|
-
inline Wrapper<T*>::Wrapper(T* data, bool isOwner) : data_(data)
|
|
9670
|
+
inline Wrapper<T*>::Wrapper(rb_data_type_t* rb_data_type, T* data, bool isOwner) : WrapperBase(rb_data_type), data_(data)
|
|
9603
9671
|
{
|
|
9604
9672
|
this->isOwner_ = isOwner;
|
|
9605
9673
|
this->isConst_ = std::is_const_v<std::remove_pointer_t<T>>;
|
|
@@ -9608,7 +9676,8 @@ namespace Rice::detail
|
|
|
9608
9676
|
template <typename T>
|
|
9609
9677
|
inline Wrapper<T*>::~Wrapper()
|
|
9610
9678
|
{
|
|
9611
|
-
Registries::instance.instances.remove(this->get());
|
|
9679
|
+
Registries::instance.instances.remove(this->get(this->rb_data_type_));
|
|
9680
|
+
|
|
9612
9681
|
if constexpr (std::is_destructible_v<T>)
|
|
9613
9682
|
{
|
|
9614
9683
|
if (this->isOwner_)
|
|
@@ -9619,14 +9688,23 @@ namespace Rice::detail
|
|
|
9619
9688
|
}
|
|
9620
9689
|
|
|
9621
9690
|
template <typename T>
|
|
9622
|
-
inline void* Wrapper<T*>::get()
|
|
9691
|
+
inline void* Wrapper<T*>::get(rb_data_type_t* requestedType)
|
|
9623
9692
|
{
|
|
9624
|
-
|
|
9693
|
+
if (rb_typeddata_inherited_p(this->rb_data_type_, requestedType))
|
|
9694
|
+
{
|
|
9695
|
+
return (void*)this->data_;
|
|
9696
|
+
}
|
|
9697
|
+
else
|
|
9698
|
+
{
|
|
9699
|
+
throw Exception(rb_eTypeError, "wrong argument type %s (expected %s)",
|
|
9700
|
+
this->rb_data_type_->wrap_struct_name,
|
|
9701
|
+
requestedType->wrap_struct_name);
|
|
9702
|
+
}
|
|
9625
9703
|
}
|
|
9626
9704
|
|
|
9627
9705
|
// ---- Wrapper** -----
|
|
9628
9706
|
template <typename T>
|
|
9629
|
-
inline Wrapper<T**>::Wrapper(T** data, bool isOwner) : data_(data)
|
|
9707
|
+
inline Wrapper<T**>::Wrapper(rb_data_type_t* rb_data_type, T** data, bool isOwner) : WrapperBase(rb_data_type), data_(data)
|
|
9630
9708
|
{
|
|
9631
9709
|
this->isOwner_ = isOwner;
|
|
9632
9710
|
this->isConst_ = std::is_const_v<std::remove_pointer_t<std::remove_pointer_t<T>>>;
|
|
@@ -9635,7 +9713,8 @@ namespace Rice::detail
|
|
|
9635
9713
|
template <typename T>
|
|
9636
9714
|
inline Wrapper<T**>::~Wrapper()
|
|
9637
9715
|
{
|
|
9638
|
-
Registries::instance.instances.remove(this->get());
|
|
9716
|
+
Registries::instance.instances.remove(this->get(this->rb_data_type_));
|
|
9717
|
+
|
|
9639
9718
|
if constexpr (std::is_destructible_v<T>)
|
|
9640
9719
|
{
|
|
9641
9720
|
if (this->isOwner_)
|
|
@@ -9646,9 +9725,18 @@ namespace Rice::detail
|
|
|
9646
9725
|
}
|
|
9647
9726
|
|
|
9648
9727
|
template <typename T>
|
|
9649
|
-
inline void* Wrapper<T**>::get()
|
|
9728
|
+
inline void* Wrapper<T**>::get(rb_data_type_t* requestedType)
|
|
9650
9729
|
{
|
|
9651
|
-
|
|
9730
|
+
if (rb_typeddata_inherited_p(this->rb_data_type_, requestedType))
|
|
9731
|
+
{
|
|
9732
|
+
return (void*)this->data_;
|
|
9733
|
+
}
|
|
9734
|
+
else
|
|
9735
|
+
{
|
|
9736
|
+
throw Exception(rb_eTypeError, "wrong argument type %s (expected %s)",
|
|
9737
|
+
this->rb_data_type_->wrap_struct_name,
|
|
9738
|
+
requestedType->wrap_struct_name);
|
|
9739
|
+
}
|
|
9652
9740
|
}
|
|
9653
9741
|
|
|
9654
9742
|
// ---- Helper Functions -------
|
|
@@ -9665,7 +9753,7 @@ namespace Rice::detail
|
|
|
9665
9753
|
// If Ruby is not the owner then wrap the reference
|
|
9666
9754
|
if (!isOwner)
|
|
9667
9755
|
{
|
|
9668
|
-
wrapper = new Wrapper<T&>(data);
|
|
9756
|
+
wrapper = new Wrapper<T&>(rb_data_type, data);
|
|
9669
9757
|
result = TypedData_Wrap_Struct(klass, rb_data_type, wrapper);
|
|
9670
9758
|
}
|
|
9671
9759
|
|
|
@@ -9674,12 +9762,12 @@ namespace Rice::detail
|
|
|
9674
9762
|
{
|
|
9675
9763
|
if constexpr (std::is_copy_constructible_v<typename T::value_type>)
|
|
9676
9764
|
{
|
|
9677
|
-
wrapper = new Wrapper<T>(data);
|
|
9765
|
+
wrapper = new Wrapper<T>(rb_data_type, data);
|
|
9678
9766
|
result = TypedData_Wrap_Struct(klass, rb_data_type, wrapper);
|
|
9679
9767
|
}
|
|
9680
9768
|
else
|
|
9681
9769
|
{
|
|
9682
|
-
wrapper = new Wrapper<T>(std::move(data));
|
|
9770
|
+
wrapper = new Wrapper<T>(rb_data_type, std::move(data));
|
|
9683
9771
|
result = TypedData_Wrap_Struct(klass, rb_data_type, wrapper);
|
|
9684
9772
|
}
|
|
9685
9773
|
}
|
|
@@ -9687,14 +9775,14 @@ namespace Rice::detail
|
|
|
9687
9775
|
// Ruby is the owner so copy data
|
|
9688
9776
|
else if constexpr (std::is_copy_constructible_v<T>)
|
|
9689
9777
|
{
|
|
9690
|
-
wrapper = new Wrapper<T>(data);
|
|
9778
|
+
wrapper = new Wrapper<T>(rb_data_type, data);
|
|
9691
9779
|
result = TypedData_Wrap_Struct(klass, rb_data_type, wrapper);
|
|
9692
9780
|
}
|
|
9693
9781
|
|
|
9694
9782
|
// Ruby is the owner so move data
|
|
9695
9783
|
else if constexpr (std::is_move_constructible_v<T>)
|
|
9696
9784
|
{
|
|
9697
|
-
wrapper = new Wrapper<T>(std::move(data));
|
|
9785
|
+
wrapper = new Wrapper<T>(rb_data_type, std::move(data));
|
|
9698
9786
|
result = TypedData_Wrap_Struct(klass, rb_data_type, wrapper);
|
|
9699
9787
|
}
|
|
9700
9788
|
|
|
@@ -9706,7 +9794,7 @@ namespace Rice::detail
|
|
|
9706
9794
|
throw std::runtime_error(message);
|
|
9707
9795
|
}
|
|
9708
9796
|
|
|
9709
|
-
Registries::instance.instances.add(wrapper->get(), result);
|
|
9797
|
+
Registries::instance.instances.add(wrapper->get(rb_data_type), result);
|
|
9710
9798
|
|
|
9711
9799
|
return result;
|
|
9712
9800
|
};
|
|
@@ -9719,38 +9807,40 @@ namespace Rice::detail
|
|
|
9719
9807
|
if (result != Qnil)
|
|
9720
9808
|
return result;
|
|
9721
9809
|
|
|
9722
|
-
WrapperBase* wrapper = new Wrapper<T*>(data, isOwner);
|
|
9810
|
+
WrapperBase* wrapper = new Wrapper<T*>(rb_data_type, data, isOwner);
|
|
9723
9811
|
result = TypedData_Wrap_Struct(klass, rb_data_type, wrapper);
|
|
9724
9812
|
|
|
9725
|
-
Registries::instance.instances.add(wrapper->get(), result);
|
|
9813
|
+
Registries::instance.instances.add(wrapper->get(rb_data_type), result);
|
|
9726
9814
|
return result;
|
|
9727
9815
|
};
|
|
9728
9816
|
|
|
9729
9817
|
template <typename T>
|
|
9730
9818
|
inline T* unwrap(VALUE value, rb_data_type_t* rb_data_type, bool takeOwnership)
|
|
9731
9819
|
{
|
|
9732
|
-
if (
|
|
9820
|
+
if (!RTYPEDDATA_P(value))
|
|
9733
9821
|
{
|
|
9734
9822
|
std::string message = "The Ruby object does not wrap a C++ object. It is actually a " +
|
|
9735
9823
|
std::string(detail::protect(rb_obj_classname, value)) + ".";
|
|
9736
9824
|
throw std::runtime_error(message);
|
|
9737
9825
|
}
|
|
9738
9826
|
|
|
9739
|
-
WrapperBase* wrapper =
|
|
9827
|
+
WrapperBase* wrapper = static_cast<WrapperBase*>(RTYPEDDATA_DATA(value));
|
|
9740
9828
|
|
|
9741
9829
|
if (wrapper == nullptr)
|
|
9742
9830
|
{
|
|
9743
|
-
std::string message = "Wrapped C++ object is nil. Did you override " +
|
|
9744
|
-
std::string(detail::protect(rb_obj_classname, value)) +
|
|
9831
|
+
std::string message = "Wrapped C++ object is nil. Did you override " +
|
|
9832
|
+
std::string(detail::protect(rb_obj_classname, value)) +
|
|
9745
9833
|
"#initialize and forget to call super?";
|
|
9746
9834
|
|
|
9747
9835
|
throw std::runtime_error(message);
|
|
9748
9836
|
}
|
|
9749
9837
|
|
|
9750
9838
|
if (takeOwnership)
|
|
9839
|
+
{
|
|
9751
9840
|
wrapper->setOwner(false);
|
|
9841
|
+
}
|
|
9752
9842
|
|
|
9753
|
-
return static_cast<T*>(wrapper->get());
|
|
9843
|
+
return static_cast<T*>(wrapper->get(rb_data_type));
|
|
9754
9844
|
}
|
|
9755
9845
|
|
|
9756
9846
|
template <typename Wrapper_T>
|
|
@@ -9772,7 +9862,8 @@ namespace Rice::detail
|
|
|
9772
9862
|
if (!RTYPEDDATA_P(value))
|
|
9773
9863
|
{
|
|
9774
9864
|
throw Exception(rb_eTypeError, "wrong argument type %s (expected %s)",
|
|
9775
|
-
|
|
9865
|
+
detail::protect(rb_obj_classname, value),
|
|
9866
|
+
"wrapped C++ object");
|
|
9776
9867
|
}
|
|
9777
9868
|
|
|
9778
9869
|
return static_cast<WrapperBase*>(RTYPEDDATA_DATA(value));
|
|
@@ -9786,21 +9877,21 @@ namespace Rice::detail
|
|
|
9786
9877
|
inline void wrapConstructed(VALUE value, rb_data_type_t* rb_data_type, T* data)
|
|
9787
9878
|
{
|
|
9788
9879
|
using Wrapper_T = Wrapper<T*>;
|
|
9789
|
-
|
|
9880
|
+
|
|
9790
9881
|
Wrapper_T* wrapper = nullptr;
|
|
9791
9882
|
TypedData_Get_Struct(value, Wrapper_T, rb_data_type, wrapper);
|
|
9792
9883
|
if (wrapper)
|
|
9793
9884
|
{
|
|
9794
|
-
Registries::instance.instances.remove(wrapper->get());
|
|
9885
|
+
Registries::instance.instances.remove(wrapper->get(rb_data_type));
|
|
9795
9886
|
delete wrapper;
|
|
9796
9887
|
}
|
|
9797
9888
|
|
|
9798
|
-
wrapper = new Wrapper_T(data, true);
|
|
9889
|
+
wrapper = new Wrapper_T(rb_data_type, data, true);
|
|
9799
9890
|
RTYPEDDATA_DATA(value) = wrapper;
|
|
9800
9891
|
|
|
9801
9892
|
Registries::instance.instances.add(data, value);
|
|
9802
9893
|
}
|
|
9803
|
-
}
|
|
9894
|
+
}
|
|
9804
9895
|
|
|
9805
9896
|
// ========= Native.ipp =========
|
|
9806
9897
|
namespace Rice::detail
|
|
@@ -12119,6 +12210,11 @@ namespace Rice
|
|
|
12119
12210
|
return RB_TEST(result);
|
|
12120
12211
|
}
|
|
12121
12212
|
|
|
12213
|
+
inline void Object::extend(Module const& mod)
|
|
12214
|
+
{
|
|
12215
|
+
detail::protect(rb_extend_object, this->value(), mod.value());
|
|
12216
|
+
}
|
|
12217
|
+
|
|
12122
12218
|
inline bool Object::respond_to(Identifier id) const
|
|
12123
12219
|
{
|
|
12124
12220
|
return bool(rb_respond_to(this->value(), id.id()));
|
|
@@ -13513,6 +13609,11 @@ namespace Rice
|
|
|
13513
13609
|
return result;
|
|
13514
13610
|
}
|
|
13515
13611
|
|
|
13612
|
+
inline Class Class::superclass() const
|
|
13613
|
+
{
|
|
13614
|
+
return detail::protect(rb_class_superclass, this->value());
|
|
13615
|
+
}
|
|
13616
|
+
|
|
13516
13617
|
inline Class define_class_under(Object parent, Identifier id, const Class& superclass)
|
|
13517
13618
|
{
|
|
13518
13619
|
VALUE klass = detail::protect(rb_define_class_id_under, parent.value(), id, superclass.value());
|
|
@@ -14067,17 +14168,22 @@ namespace Rice
|
|
|
14067
14168
|
template<typename T>
|
|
14068
14169
|
inline void ruby_mark_internal(detail::WrapperBase* wrapper)
|
|
14069
14170
|
{
|
|
14070
|
-
|
|
14071
|
-
|
|
14171
|
+
detail::cpp_protect([&]
|
|
14172
|
+
{
|
|
14173
|
+
// Tell the wrapper to mark the objects its keeping alive
|
|
14174
|
+
wrapper->ruby_mark();
|
|
14072
14175
|
|
|
14073
|
-
|
|
14074
|
-
|
|
14075
|
-
|
|
14176
|
+
// Get the underlying data and call custom mark function (if any)
|
|
14177
|
+
// Use the wrapper's stored rb_data_type to avoid type mismatch
|
|
14178
|
+
T* data = static_cast<T*>(wrapper->get(Data_Type<T>::ruby_data_type()));
|
|
14179
|
+
ruby_mark<T>(data);
|
|
14180
|
+
});
|
|
14076
14181
|
}
|
|
14077
14182
|
|
|
14078
14183
|
template<typename T>
|
|
14079
14184
|
inline void ruby_free_internal(detail::WrapperBase* wrapper)
|
|
14080
14185
|
{
|
|
14186
|
+
// Destructors are noexcept so we cannot use cpp_protect here
|
|
14081
14187
|
delete wrapper;
|
|
14082
14188
|
}
|
|
14083
14189
|
|
|
@@ -15662,6 +15768,86 @@ namespace Rice
|
|
|
15662
15768
|
}
|
|
15663
15769
|
}
|
|
15664
15770
|
|
|
15771
|
+
// Dependent on Module, Array, Symbol - used by stl smart pointers
|
|
15772
|
+
|
|
15773
|
+
// ========= Forwards.hpp =========
|
|
15774
|
+
|
|
15775
|
+
namespace Rice::detail
|
|
15776
|
+
{
|
|
15777
|
+
// Setup method forwarding from a wrapper class to its wrapped type using Ruby's Forwardable.
|
|
15778
|
+
// This allows calling methods on the wrapper that get delegated to the wrapped object via
|
|
15779
|
+
// a "get" method that returns the wrapped object.
|
|
15780
|
+
//
|
|
15781
|
+
// Parameters:
|
|
15782
|
+
// wrapper_klass - The Ruby class to add forwarding to (e.g., SharedPtr_MyClass)
|
|
15783
|
+
// wrapped_klass - The Ruby class whose methods should be forwarded (e.g., MyClass)
|
|
15784
|
+
void define_forwarding(VALUE wrapper_klass, VALUE wrapped_klass);
|
|
15785
|
+
}
|
|
15786
|
+
|
|
15787
|
+
|
|
15788
|
+
// --------- Forwards.ipp ---------
|
|
15789
|
+
namespace Rice::detail
|
|
15790
|
+
{
|
|
15791
|
+
inline void define_forwarding(VALUE wrapper_klass, VALUE wrapped_klass)
|
|
15792
|
+
{
|
|
15793
|
+
protect(rb_require, "forwardable");
|
|
15794
|
+
Object forwardable = Object(rb_cObject).const_get("Forwardable");
|
|
15795
|
+
Object(wrapper_klass).extend(forwardable.value());
|
|
15796
|
+
|
|
15797
|
+
// Get wrapper class's method names to avoid conflicts
|
|
15798
|
+
std::set<std::string> wrapperMethodSet;
|
|
15799
|
+
for (Native* native : Registries::instance.natives.lookup(wrapper_klass, NativeKind::Method))
|
|
15800
|
+
{
|
|
15801
|
+
wrapperMethodSet.insert(native->name());
|
|
15802
|
+
}
|
|
15803
|
+
for (Native* native : Registries::instance.natives.lookup(wrapper_klass, NativeKind::AttributeReader))
|
|
15804
|
+
{
|
|
15805
|
+
wrapperMethodSet.insert(native->name());
|
|
15806
|
+
}
|
|
15807
|
+
for (Native* native : Registries::instance.natives.lookup(wrapper_klass, NativeKind::AttributeWriter))
|
|
15808
|
+
{
|
|
15809
|
+
wrapperMethodSet.insert(native->name() + "=");
|
|
15810
|
+
}
|
|
15811
|
+
|
|
15812
|
+
// Get wrapped class's method names from the registry, including ancestor classes
|
|
15813
|
+
std::set<std::string> wrappedMethodSet;
|
|
15814
|
+
Class klass(wrapped_klass);
|
|
15815
|
+
while (klass.value() != rb_cObject && klass.value() != Qnil)
|
|
15816
|
+
{
|
|
15817
|
+
for (Native* native : Registries::instance.natives.lookup(klass.value(), NativeKind::Method))
|
|
15818
|
+
{
|
|
15819
|
+
wrappedMethodSet.insert(native->name());
|
|
15820
|
+
}
|
|
15821
|
+
for (Native* native : Registries::instance.natives.lookup(klass.value(), NativeKind::AttributeReader))
|
|
15822
|
+
{
|
|
15823
|
+
wrappedMethodSet.insert(native->name());
|
|
15824
|
+
}
|
|
15825
|
+
for (Native* native : Registries::instance.natives.lookup(klass.value(), NativeKind::AttributeWriter))
|
|
15826
|
+
{
|
|
15827
|
+
wrappedMethodSet.insert(native->name() + "=");
|
|
15828
|
+
}
|
|
15829
|
+
|
|
15830
|
+
klass = klass.superclass();
|
|
15831
|
+
}
|
|
15832
|
+
|
|
15833
|
+
// Build the arguments array for def_delegators: [:get, :method1, :method2, ...]
|
|
15834
|
+
// Skip methods that are already defined on the wrapper class
|
|
15835
|
+
Array args;
|
|
15836
|
+
args.push(Symbol("get"));
|
|
15837
|
+
for (const std::string& method : wrappedMethodSet)
|
|
15838
|
+
{
|
|
15839
|
+
if (wrapperMethodSet.find(method) == wrapperMethodSet.end())
|
|
15840
|
+
{
|
|
15841
|
+
args.push(Symbol(method));
|
|
15842
|
+
}
|
|
15843
|
+
}
|
|
15844
|
+
|
|
15845
|
+
// Call def_delegators(*args)
|
|
15846
|
+
Object(wrapper_klass).vcall("def_delegators", args);
|
|
15847
|
+
}
|
|
15848
|
+
}
|
|
15849
|
+
|
|
15850
|
+
|
|
15665
15851
|
// For now include libc support - maybe should be separate header file someday
|
|
15666
15852
|
|
|
15667
15853
|
// ========= file.hpp =========
|