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
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
namespace Rice::detail
|
|
2
|
+
{
|
|
3
|
+
inline void define_forwarding(VALUE wrapper_klass, VALUE wrapped_klass)
|
|
4
|
+
{
|
|
5
|
+
protect(rb_require, "forwardable");
|
|
6
|
+
Object forwardable = Object(rb_cObject).const_get("Forwardable");
|
|
7
|
+
Object(wrapper_klass).extend(forwardable.value());
|
|
8
|
+
|
|
9
|
+
// Get wrapper class's method names to avoid conflicts
|
|
10
|
+
std::set<std::string> wrapperMethodSet;
|
|
11
|
+
for (Native* native : Registries::instance.natives.lookup(wrapper_klass, NativeKind::Method))
|
|
12
|
+
{
|
|
13
|
+
wrapperMethodSet.insert(native->name());
|
|
14
|
+
}
|
|
15
|
+
for (Native* native : Registries::instance.natives.lookup(wrapper_klass, NativeKind::AttributeReader))
|
|
16
|
+
{
|
|
17
|
+
wrapperMethodSet.insert(native->name());
|
|
18
|
+
}
|
|
19
|
+
for (Native* native : Registries::instance.natives.lookup(wrapper_klass, NativeKind::AttributeWriter))
|
|
20
|
+
{
|
|
21
|
+
wrapperMethodSet.insert(native->name() + "=");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Get wrapped class's method names from the registry, including ancestor classes
|
|
25
|
+
std::set<std::string> wrappedMethodSet;
|
|
26
|
+
Class klass(wrapped_klass);
|
|
27
|
+
while (klass.value() != rb_cObject && klass.value() != Qnil)
|
|
28
|
+
{
|
|
29
|
+
for (Native* native : Registries::instance.natives.lookup(klass.value(), NativeKind::Method))
|
|
30
|
+
{
|
|
31
|
+
wrappedMethodSet.insert(native->name());
|
|
32
|
+
}
|
|
33
|
+
for (Native* native : Registries::instance.natives.lookup(klass.value(), NativeKind::AttributeReader))
|
|
34
|
+
{
|
|
35
|
+
wrappedMethodSet.insert(native->name());
|
|
36
|
+
}
|
|
37
|
+
for (Native* native : Registries::instance.natives.lookup(klass.value(), NativeKind::AttributeWriter))
|
|
38
|
+
{
|
|
39
|
+
wrappedMethodSet.insert(native->name() + "=");
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
klass = klass.superclass();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Build the arguments array for def_delegators: [:get, :method1, :method2, ...]
|
|
46
|
+
// Skip methods that are already defined on the wrapper class
|
|
47
|
+
Array args;
|
|
48
|
+
args.push(Symbol("get"));
|
|
49
|
+
for (const std::string& method : wrappedMethodSet)
|
|
50
|
+
{
|
|
51
|
+
if (wrapperMethodSet.find(method) == wrapperMethodSet.end())
|
|
52
|
+
{
|
|
53
|
+
args.push(Symbol(method));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Call def_delegators(*args)
|
|
58
|
+
Object(wrapper_klass).vcall("def_delegators", args);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -35,6 +35,7 @@ namespace Rice::detail
|
|
|
35
35
|
|
|
36
36
|
const std::vector<Native*> lookup(VALUE klass);
|
|
37
37
|
const std::vector<std::unique_ptr<Native>>& lookup(VALUE klass, ID methodId);
|
|
38
|
+
std::vector<Native*> lookup(VALUE klass, NativeKind kind);
|
|
38
39
|
|
|
39
40
|
private:
|
|
40
41
|
// Key - Ruby klass/method
|
|
@@ -72,4 +72,33 @@ namespace Rice::detail
|
|
|
72
72
|
// Lookup items for method
|
|
73
73
|
return this->natives_[key];
|
|
74
74
|
}
|
|
75
|
+
|
|
76
|
+
inline std::vector<Native*> NativeRegistry::lookup(VALUE klass, NativeKind kind)
|
|
77
|
+
{
|
|
78
|
+
std::vector<Native*> result;
|
|
79
|
+
|
|
80
|
+
if (rb_type(klass) == T_ICLASS)
|
|
81
|
+
{
|
|
82
|
+
klass = detail::protect(rb_class_of, klass);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
for (auto& pair : this->natives_)
|
|
86
|
+
{
|
|
87
|
+
const std::pair<VALUE, ID>& key = pair.first;
|
|
88
|
+
|
|
89
|
+
if (klass == key.first)
|
|
90
|
+
{
|
|
91
|
+
const std::vector<std::unique_ptr<Native>>& natives = pair.second;
|
|
92
|
+
for (auto& native : natives)
|
|
93
|
+
{
|
|
94
|
+
if (native->kind() == kind)
|
|
95
|
+
{
|
|
96
|
+
result.push_back(native.get());
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return result;
|
|
103
|
+
}
|
|
75
104
|
}
|
data/rice/detail/Type.ipp
CHANGED
|
@@ -209,6 +209,10 @@ namespace Rice::detail
|
|
|
209
209
|
std::regex equalRegex(R"(,\s*std::equal_to)");
|
|
210
210
|
removeGroup(base, equalRegex);
|
|
211
211
|
|
|
212
|
+
// Remove default_delete (std::unique_ptr)
|
|
213
|
+
std::regex defaultDeleteRegex(R"(,\s*std::default_delete)");
|
|
214
|
+
removeGroup(base, defaultDeleteRegex);
|
|
215
|
+
|
|
212
216
|
// Remove spaces before pointers
|
|
213
217
|
std::regex ptrRegex = std::regex(R"(\s+\*)");
|
|
214
218
|
base = std::regex_replace(base, ptrRegex, "*");
|
data/rice/detail/Wrapper.hpp
CHANGED
|
@@ -6,9 +6,9 @@ namespace Rice::detail
|
|
|
6
6
|
class WrapperBase
|
|
7
7
|
{
|
|
8
8
|
public:
|
|
9
|
-
WrapperBase()
|
|
9
|
+
WrapperBase(rb_data_type_t* rb_data_type);
|
|
10
10
|
virtual ~WrapperBase() = default;
|
|
11
|
-
virtual void* get() = 0;
|
|
11
|
+
virtual void* get(rb_data_type_t* requestedType) = 0;
|
|
12
12
|
bool isConst();
|
|
13
13
|
|
|
14
14
|
void ruby_mark();
|
|
@@ -16,6 +16,7 @@ namespace Rice::detail
|
|
|
16
16
|
void setOwner(bool value);
|
|
17
17
|
|
|
18
18
|
protected:
|
|
19
|
+
rb_data_type_t* rb_data_type_;
|
|
19
20
|
bool isOwner_ = false;
|
|
20
21
|
bool isConst_ = false;
|
|
21
22
|
|
|
@@ -30,10 +31,10 @@ namespace Rice::detail
|
|
|
30
31
|
class Wrapper : public WrapperBase
|
|
31
32
|
{
|
|
32
33
|
public:
|
|
33
|
-
Wrapper(T& data);
|
|
34
|
-
Wrapper(T&& data);
|
|
34
|
+
Wrapper(rb_data_type_t* rb_data_type, T& data);
|
|
35
|
+
Wrapper(rb_data_type_t* rb_data_type, T&& data);
|
|
35
36
|
~Wrapper();
|
|
36
|
-
void* get() override;
|
|
37
|
+
void* get(rb_data_type_t* requestedType) override;
|
|
37
38
|
|
|
38
39
|
private:
|
|
39
40
|
T data_;
|
|
@@ -43,9 +44,9 @@ namespace Rice::detail
|
|
|
43
44
|
class Wrapper<T&> : public WrapperBase
|
|
44
45
|
{
|
|
45
46
|
public:
|
|
46
|
-
Wrapper(T& data);
|
|
47
|
+
Wrapper(rb_data_type_t* rb_data_type, T& data);
|
|
47
48
|
~Wrapper();
|
|
48
|
-
void* get() override;
|
|
49
|
+
void* get(rb_data_type_t* requestedType) override;
|
|
49
50
|
|
|
50
51
|
private:
|
|
51
52
|
T& data_;
|
|
@@ -55,9 +56,9 @@ namespace Rice::detail
|
|
|
55
56
|
class Wrapper<T*> : public WrapperBase
|
|
56
57
|
{
|
|
57
58
|
public:
|
|
58
|
-
Wrapper(T* data, bool isOwner);
|
|
59
|
+
Wrapper(rb_data_type_t* rb_data_type, T* data, bool isOwner);
|
|
59
60
|
~Wrapper();
|
|
60
|
-
void* get() override;
|
|
61
|
+
void* get(rb_data_type_t* requestedType) override;
|
|
61
62
|
|
|
62
63
|
private:
|
|
63
64
|
T* data_ = nullptr;
|
|
@@ -67,9 +68,9 @@ namespace Rice::detail
|
|
|
67
68
|
class Wrapper<T**> : public WrapperBase
|
|
68
69
|
{
|
|
69
70
|
public:
|
|
70
|
-
Wrapper(T** data, bool isOwner);
|
|
71
|
+
Wrapper(rb_data_type_t* rb_data_type, T** data, bool isOwner);
|
|
71
72
|
~Wrapper();
|
|
72
|
-
void* get() override;
|
|
73
|
+
void* get(rb_data_type_t* requestedType) override;
|
|
73
74
|
|
|
74
75
|
private:
|
|
75
76
|
T** data_ = nullptr;
|
data/rice/detail/Wrapper.ipp
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
namespace Rice::detail
|
|
4
4
|
{
|
|
5
|
+
inline WrapperBase::WrapperBase(rb_data_type_t* rb_data_type) : rb_data_type_(rb_data_type)
|
|
6
|
+
{
|
|
7
|
+
}
|
|
8
|
+
|
|
5
9
|
inline bool WrapperBase::isConst()
|
|
6
10
|
{
|
|
7
11
|
return this->isConst_;
|
|
@@ -27,31 +31,40 @@ namespace Rice::detail
|
|
|
27
31
|
|
|
28
32
|
// ---- Wrapper -----
|
|
29
33
|
template <typename T>
|
|
30
|
-
inline Wrapper<T>::Wrapper(T& data): data_(data)
|
|
34
|
+
inline Wrapper<T>::Wrapper(rb_data_type_t* rb_data_type, T& data) : WrapperBase(rb_data_type), data_(data)
|
|
31
35
|
{
|
|
32
36
|
this->isConst_ = std::is_const_v<std::remove_reference_t<T>>;
|
|
33
37
|
}
|
|
34
38
|
|
|
35
39
|
template <typename T>
|
|
36
|
-
inline Wrapper<T>::Wrapper(T&& data) : data_(std::move(data))
|
|
40
|
+
inline Wrapper<T>::Wrapper(rb_data_type_t* rb_data_type, T&& data) : WrapperBase(rb_data_type), data_(std::move(data))
|
|
37
41
|
{
|
|
38
42
|
}
|
|
39
43
|
|
|
40
44
|
template <typename T>
|
|
41
45
|
inline Wrapper<T>::~Wrapper()
|
|
42
46
|
{
|
|
43
|
-
Registries::instance.instances.remove(this->get());
|
|
47
|
+
Registries::instance.instances.remove(this->get(this->rb_data_type_));
|
|
44
48
|
}
|
|
45
49
|
|
|
46
50
|
template <typename T>
|
|
47
|
-
inline void* Wrapper<T>::
|
|
51
|
+
inline void* Wrapper<T>::get(rb_data_type_t* requestedType)
|
|
48
52
|
{
|
|
49
|
-
|
|
53
|
+
if (rb_typeddata_inherited_p(this->rb_data_type_, requestedType))
|
|
54
|
+
{
|
|
55
|
+
return (void*)&this->data_;
|
|
56
|
+
}
|
|
57
|
+
else
|
|
58
|
+
{
|
|
59
|
+
throw Exception(rb_eTypeError, "wrong argument type %s (expected %s)",
|
|
60
|
+
this->rb_data_type_->wrap_struct_name,
|
|
61
|
+
requestedType->wrap_struct_name);
|
|
62
|
+
}
|
|
50
63
|
}
|
|
51
64
|
|
|
52
65
|
// ---- Wrapper& -----
|
|
53
66
|
template <typename T>
|
|
54
|
-
inline Wrapper<T&>::Wrapper(T& data): data_(data)
|
|
67
|
+
inline Wrapper<T&>::Wrapper(rb_data_type_t* rb_data_type, T& data) : WrapperBase(rb_data_type), data_(data)
|
|
55
68
|
{
|
|
56
69
|
this->isConst_ = std::is_const_v<std::remove_reference_t<T>>;
|
|
57
70
|
}
|
|
@@ -59,18 +72,27 @@ namespace Rice::detail
|
|
|
59
72
|
template <typename T>
|
|
60
73
|
inline Wrapper<T&>::~Wrapper()
|
|
61
74
|
{
|
|
62
|
-
Registries::instance.instances.remove(this->get());
|
|
75
|
+
Registries::instance.instances.remove(this->get(this->rb_data_type_));
|
|
63
76
|
}
|
|
64
77
|
|
|
65
78
|
template <typename T>
|
|
66
|
-
inline void* Wrapper<T&>::get()
|
|
79
|
+
inline void* Wrapper<T&>::get(rb_data_type_t* requestedType)
|
|
67
80
|
{
|
|
68
|
-
|
|
81
|
+
if (rb_typeddata_inherited_p(this->rb_data_type_, requestedType))
|
|
82
|
+
{
|
|
83
|
+
return (void*)&this->data_;
|
|
84
|
+
}
|
|
85
|
+
else
|
|
86
|
+
{
|
|
87
|
+
throw Exception(rb_eTypeError, "wrong argument type %s (expected %s)",
|
|
88
|
+
this->rb_data_type_->wrap_struct_name,
|
|
89
|
+
requestedType->wrap_struct_name);
|
|
90
|
+
}
|
|
69
91
|
}
|
|
70
92
|
|
|
71
93
|
// ---- Wrapper* -----
|
|
72
94
|
template <typename T>
|
|
73
|
-
inline Wrapper<T*>::Wrapper(T* data, bool isOwner) : data_(data)
|
|
95
|
+
inline Wrapper<T*>::Wrapper(rb_data_type_t* rb_data_type, T* data, bool isOwner) : WrapperBase(rb_data_type), data_(data)
|
|
74
96
|
{
|
|
75
97
|
this->isOwner_ = isOwner;
|
|
76
98
|
this->isConst_ = std::is_const_v<std::remove_pointer_t<T>>;
|
|
@@ -79,7 +101,8 @@ namespace Rice::detail
|
|
|
79
101
|
template <typename T>
|
|
80
102
|
inline Wrapper<T*>::~Wrapper()
|
|
81
103
|
{
|
|
82
|
-
Registries::instance.instances.remove(this->get());
|
|
104
|
+
Registries::instance.instances.remove(this->get(this->rb_data_type_));
|
|
105
|
+
|
|
83
106
|
if constexpr (std::is_destructible_v<T>)
|
|
84
107
|
{
|
|
85
108
|
if (this->isOwner_)
|
|
@@ -90,14 +113,23 @@ namespace Rice::detail
|
|
|
90
113
|
}
|
|
91
114
|
|
|
92
115
|
template <typename T>
|
|
93
|
-
inline void* Wrapper<T*>::get()
|
|
116
|
+
inline void* Wrapper<T*>::get(rb_data_type_t* requestedType)
|
|
94
117
|
{
|
|
95
|
-
|
|
118
|
+
if (rb_typeddata_inherited_p(this->rb_data_type_, requestedType))
|
|
119
|
+
{
|
|
120
|
+
return (void*)this->data_;
|
|
121
|
+
}
|
|
122
|
+
else
|
|
123
|
+
{
|
|
124
|
+
throw Exception(rb_eTypeError, "wrong argument type %s (expected %s)",
|
|
125
|
+
this->rb_data_type_->wrap_struct_name,
|
|
126
|
+
requestedType->wrap_struct_name);
|
|
127
|
+
}
|
|
96
128
|
}
|
|
97
129
|
|
|
98
130
|
// ---- Wrapper** -----
|
|
99
131
|
template <typename T>
|
|
100
|
-
inline Wrapper<T**>::Wrapper(T** data, bool isOwner) : data_(data)
|
|
132
|
+
inline Wrapper<T**>::Wrapper(rb_data_type_t* rb_data_type, T** data, bool isOwner) : WrapperBase(rb_data_type), data_(data)
|
|
101
133
|
{
|
|
102
134
|
this->isOwner_ = isOwner;
|
|
103
135
|
this->isConst_ = std::is_const_v<std::remove_pointer_t<std::remove_pointer_t<T>>>;
|
|
@@ -106,7 +138,8 @@ namespace Rice::detail
|
|
|
106
138
|
template <typename T>
|
|
107
139
|
inline Wrapper<T**>::~Wrapper()
|
|
108
140
|
{
|
|
109
|
-
Registries::instance.instances.remove(this->get());
|
|
141
|
+
Registries::instance.instances.remove(this->get(this->rb_data_type_));
|
|
142
|
+
|
|
110
143
|
if constexpr (std::is_destructible_v<T>)
|
|
111
144
|
{
|
|
112
145
|
if (this->isOwner_)
|
|
@@ -117,9 +150,18 @@ namespace Rice::detail
|
|
|
117
150
|
}
|
|
118
151
|
|
|
119
152
|
template <typename T>
|
|
120
|
-
inline void* Wrapper<T**>::get()
|
|
153
|
+
inline void* Wrapper<T**>::get(rb_data_type_t* requestedType)
|
|
121
154
|
{
|
|
122
|
-
|
|
155
|
+
if (rb_typeddata_inherited_p(this->rb_data_type_, requestedType))
|
|
156
|
+
{
|
|
157
|
+
return (void*)this->data_;
|
|
158
|
+
}
|
|
159
|
+
else
|
|
160
|
+
{
|
|
161
|
+
throw Exception(rb_eTypeError, "wrong argument type %s (expected %s)",
|
|
162
|
+
this->rb_data_type_->wrap_struct_name,
|
|
163
|
+
requestedType->wrap_struct_name);
|
|
164
|
+
}
|
|
123
165
|
}
|
|
124
166
|
|
|
125
167
|
// ---- Helper Functions -------
|
|
@@ -136,7 +178,7 @@ namespace Rice::detail
|
|
|
136
178
|
// If Ruby is not the owner then wrap the reference
|
|
137
179
|
if (!isOwner)
|
|
138
180
|
{
|
|
139
|
-
wrapper = new Wrapper<T&>(data);
|
|
181
|
+
wrapper = new Wrapper<T&>(rb_data_type, data);
|
|
140
182
|
result = TypedData_Wrap_Struct(klass, rb_data_type, wrapper);
|
|
141
183
|
}
|
|
142
184
|
|
|
@@ -145,12 +187,12 @@ namespace Rice::detail
|
|
|
145
187
|
{
|
|
146
188
|
if constexpr (std::is_copy_constructible_v<typename T::value_type>)
|
|
147
189
|
{
|
|
148
|
-
wrapper = new Wrapper<T>(data);
|
|
190
|
+
wrapper = new Wrapper<T>(rb_data_type, data);
|
|
149
191
|
result = TypedData_Wrap_Struct(klass, rb_data_type, wrapper);
|
|
150
192
|
}
|
|
151
193
|
else
|
|
152
194
|
{
|
|
153
|
-
wrapper = new Wrapper<T>(std::move(data));
|
|
195
|
+
wrapper = new Wrapper<T>(rb_data_type, std::move(data));
|
|
154
196
|
result = TypedData_Wrap_Struct(klass, rb_data_type, wrapper);
|
|
155
197
|
}
|
|
156
198
|
}
|
|
@@ -158,14 +200,14 @@ namespace Rice::detail
|
|
|
158
200
|
// Ruby is the owner so copy data
|
|
159
201
|
else if constexpr (std::is_copy_constructible_v<T>)
|
|
160
202
|
{
|
|
161
|
-
wrapper = new Wrapper<T>(data);
|
|
203
|
+
wrapper = new Wrapper<T>(rb_data_type, data);
|
|
162
204
|
result = TypedData_Wrap_Struct(klass, rb_data_type, wrapper);
|
|
163
205
|
}
|
|
164
206
|
|
|
165
207
|
// Ruby is the owner so move data
|
|
166
208
|
else if constexpr (std::is_move_constructible_v<T>)
|
|
167
209
|
{
|
|
168
|
-
wrapper = new Wrapper<T>(std::move(data));
|
|
210
|
+
wrapper = new Wrapper<T>(rb_data_type, std::move(data));
|
|
169
211
|
result = TypedData_Wrap_Struct(klass, rb_data_type, wrapper);
|
|
170
212
|
}
|
|
171
213
|
|
|
@@ -177,7 +219,7 @@ namespace Rice::detail
|
|
|
177
219
|
throw std::runtime_error(message);
|
|
178
220
|
}
|
|
179
221
|
|
|
180
|
-
Registries::instance.instances.add(wrapper->get(), result);
|
|
222
|
+
Registries::instance.instances.add(wrapper->get(rb_data_type), result);
|
|
181
223
|
|
|
182
224
|
return result;
|
|
183
225
|
};
|
|
@@ -190,38 +232,40 @@ namespace Rice::detail
|
|
|
190
232
|
if (result != Qnil)
|
|
191
233
|
return result;
|
|
192
234
|
|
|
193
|
-
WrapperBase* wrapper = new Wrapper<T*>(data, isOwner);
|
|
235
|
+
WrapperBase* wrapper = new Wrapper<T*>(rb_data_type, data, isOwner);
|
|
194
236
|
result = TypedData_Wrap_Struct(klass, rb_data_type, wrapper);
|
|
195
237
|
|
|
196
|
-
Registries::instance.instances.add(wrapper->get(), result);
|
|
238
|
+
Registries::instance.instances.add(wrapper->get(rb_data_type), result);
|
|
197
239
|
return result;
|
|
198
240
|
};
|
|
199
241
|
|
|
200
242
|
template <typename T>
|
|
201
243
|
inline T* unwrap(VALUE value, rb_data_type_t* rb_data_type, bool takeOwnership)
|
|
202
244
|
{
|
|
203
|
-
if (
|
|
245
|
+
if (!RTYPEDDATA_P(value))
|
|
204
246
|
{
|
|
205
247
|
std::string message = "The Ruby object does not wrap a C++ object. It is actually a " +
|
|
206
248
|
std::string(detail::protect(rb_obj_classname, value)) + ".";
|
|
207
249
|
throw std::runtime_error(message);
|
|
208
250
|
}
|
|
209
251
|
|
|
210
|
-
WrapperBase* wrapper =
|
|
252
|
+
WrapperBase* wrapper = static_cast<WrapperBase*>(RTYPEDDATA_DATA(value));
|
|
211
253
|
|
|
212
254
|
if (wrapper == nullptr)
|
|
213
255
|
{
|
|
214
|
-
std::string message = "Wrapped C++ object is nil. Did you override " +
|
|
215
|
-
std::string(detail::protect(rb_obj_classname, value)) +
|
|
256
|
+
std::string message = "Wrapped C++ object is nil. Did you override " +
|
|
257
|
+
std::string(detail::protect(rb_obj_classname, value)) +
|
|
216
258
|
"#initialize and forget to call super?";
|
|
217
259
|
|
|
218
260
|
throw std::runtime_error(message);
|
|
219
261
|
}
|
|
220
262
|
|
|
221
263
|
if (takeOwnership)
|
|
264
|
+
{
|
|
222
265
|
wrapper->setOwner(false);
|
|
266
|
+
}
|
|
223
267
|
|
|
224
|
-
return static_cast<T*>(wrapper->get());
|
|
268
|
+
return static_cast<T*>(wrapper->get(rb_data_type));
|
|
225
269
|
}
|
|
226
270
|
|
|
227
271
|
template <typename Wrapper_T>
|
|
@@ -243,7 +287,8 @@ namespace Rice::detail
|
|
|
243
287
|
if (!RTYPEDDATA_P(value))
|
|
244
288
|
{
|
|
245
289
|
throw Exception(rb_eTypeError, "wrong argument type %s (expected %s)",
|
|
246
|
-
|
|
290
|
+
detail::protect(rb_obj_classname, value),
|
|
291
|
+
"wrapped C++ object");
|
|
247
292
|
}
|
|
248
293
|
|
|
249
294
|
return static_cast<WrapperBase*>(RTYPEDDATA_DATA(value));
|
|
@@ -257,18 +302,18 @@ namespace Rice::detail
|
|
|
257
302
|
inline void wrapConstructed(VALUE value, rb_data_type_t* rb_data_type, T* data)
|
|
258
303
|
{
|
|
259
304
|
using Wrapper_T = Wrapper<T*>;
|
|
260
|
-
|
|
305
|
+
|
|
261
306
|
Wrapper_T* wrapper = nullptr;
|
|
262
307
|
TypedData_Get_Struct(value, Wrapper_T, rb_data_type, wrapper);
|
|
263
308
|
if (wrapper)
|
|
264
309
|
{
|
|
265
|
-
Registries::instance.instances.remove(wrapper->get());
|
|
310
|
+
Registries::instance.instances.remove(wrapper->get(rb_data_type));
|
|
266
311
|
delete wrapper;
|
|
267
312
|
}
|
|
268
313
|
|
|
269
|
-
wrapper = new Wrapper_T(data, true);
|
|
314
|
+
wrapper = new Wrapper_T(rb_data_type, data, true);
|
|
270
315
|
RTYPEDDATA_DATA(value) = wrapper;
|
|
271
316
|
|
|
272
317
|
Registries::instance.instances.add(data, value);
|
|
273
318
|
}
|
|
274
|
-
}
|
|
319
|
+
}
|
data/rice/rice.hpp
CHANGED
|
@@ -156,6 +156,9 @@
|
|
|
156
156
|
// Dependent on Module, Class, Array and String
|
|
157
157
|
#include "forward_declares.ipp"
|
|
158
158
|
|
|
159
|
+
// Dependent on Module, Array, Symbol - used by stl smart pointers
|
|
160
|
+
#include "detail/Forwards.hpp"
|
|
161
|
+
|
|
159
162
|
// For now include libc support - maybe should be separate header file someday
|
|
160
163
|
#include "libc/file.hpp"
|
|
161
164
|
|
|
@@ -17,5 +17,18 @@ inline void Init_Native_Registry()
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
return result;
|
|
20
|
-
}, Arg("klass").setValue())
|
|
20
|
+
}, Arg("klass").setValue()).
|
|
21
|
+
|
|
22
|
+
define_method("lookup_by_kind", [](detail::NativeRegistry& self, VALUE klass, detail::NativeKind kind) -> Array
|
|
23
|
+
{
|
|
24
|
+
Array result;
|
|
25
|
+
|
|
26
|
+
const std::vector<detail::Native*> natives = self.lookup(klass, kind);
|
|
27
|
+
for (detail::Native* native : natives)
|
|
28
|
+
{
|
|
29
|
+
result.push(native, false);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return result;
|
|
33
|
+
}, Arg("klass").setValue(), Arg("kind"));
|
|
21
34
|
}
|
data/rice/stl/shared_ptr.hpp
CHANGED
|
@@ -7,6 +7,22 @@ namespace Rice
|
|
|
7
7
|
Data_Type<std::shared_ptr<T>> define_shared_ptr(std::string klassName = "");
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
+
namespace Rice::detail
|
|
11
|
+
{
|
|
12
|
+
template<typename T>
|
|
13
|
+
class Wrapper<std::shared_ptr<T>> : public WrapperBase
|
|
14
|
+
{
|
|
15
|
+
public:
|
|
16
|
+
Wrapper(rb_data_type_t* rb_data_type, const std::shared_ptr<T>& data);
|
|
17
|
+
~Wrapper();
|
|
18
|
+
void* get(rb_data_type_t* requestedType) override;
|
|
19
|
+
|
|
20
|
+
private:
|
|
21
|
+
std::shared_ptr<T> data_;
|
|
22
|
+
rb_data_type_t* inner_rb_data_type_;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
10
26
|
#include "shared_ptr.ipp"
|
|
11
27
|
|
|
12
28
|
#endif // Rice__stl__shared_ptr__hpp_
|
data/rice/stl/shared_ptr.ipp
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
#include <memory>
|
|
2
2
|
|
|
3
|
-
// --------- Enable creation of std::shared_ptr from Ruby ---------
|
|
4
3
|
namespace Rice
|
|
5
4
|
{
|
|
6
5
|
template<typename T>
|
|
@@ -22,74 +21,98 @@ namespace Rice
|
|
|
22
21
|
}
|
|
23
22
|
|
|
24
23
|
Identifier id(klassName);
|
|
25
|
-
Data_Type_T result = define_class_under<SharedPtr_T
|
|
24
|
+
Data_Type_T result = define_class_under<detail::intrinsic_type<SharedPtr_T>>(rb_mStd, id).
|
|
25
|
+
define_method("get", &SharedPtr_T::get).
|
|
26
|
+
define_method("swap", &SharedPtr_T::swap).
|
|
27
|
+
define_method("use_count", &SharedPtr_T::use_count).
|
|
28
|
+
define_method("empty?", [](SharedPtr_T& self)->bool
|
|
29
|
+
{
|
|
30
|
+
return !self;
|
|
31
|
+
});
|
|
26
32
|
|
|
27
|
-
|
|
28
|
-
// and the deleter cannot be determined. So skip the constructor for void.
|
|
29
|
-
// std::shared_ptr<T[]> (array types) also skip constructor - arrays need special handling.
|
|
30
|
-
if constexpr (!std::is_void_v<T> && !std::is_array_v<T>)
|
|
33
|
+
if constexpr (!std::is_void_v<T>)
|
|
31
34
|
{
|
|
32
35
|
result.define_constructor(Constructor<SharedPtr_T, typename SharedPtr_T::element_type*>(), Arg("value").takeOwnership());
|
|
33
36
|
}
|
|
34
37
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
// Setup delegation to forward T's methods via get (only for non-fundamental, non-void types)
|
|
39
|
+
if constexpr (!std::is_void_v<T> && !std::is_fundamental_v<T>)
|
|
40
|
+
{
|
|
41
|
+
detail::define_forwarding(result.klass(), Data_Type<T>::klass());
|
|
42
|
+
}
|
|
39
43
|
|
|
40
44
|
return result;
|
|
41
45
|
}
|
|
42
46
|
}
|
|
43
47
|
|
|
44
|
-
// ---------
|
|
48
|
+
// --------- Wrapper ---------
|
|
45
49
|
namespace Rice::detail
|
|
46
50
|
{
|
|
47
51
|
template<typename T>
|
|
48
|
-
|
|
52
|
+
Wrapper<std::shared_ptr<T>>::Wrapper(rb_data_type_t* rb_data_type, const std::shared_ptr<T>& data)
|
|
53
|
+
: WrapperBase(rb_data_type), data_(data)
|
|
49
54
|
{
|
|
50
|
-
|
|
55
|
+
using Intrinsic_T = intrinsic_type<T>;
|
|
56
|
+
|
|
57
|
+
if constexpr (std::is_fundamental_v<Intrinsic_T>)
|
|
51
58
|
{
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
if (!Type<intrinsic_type<T>>::verify())
|
|
60
|
-
{
|
|
61
|
-
return false;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
59
|
+
inner_rb_data_type_ = Data_Type<Pointer<Intrinsic_T>>::ruby_data_type();
|
|
60
|
+
}
|
|
61
|
+
else
|
|
62
|
+
{
|
|
63
|
+
inner_rb_data_type_ = Data_Type<Intrinsic_T>::ruby_data_type();
|
|
64
|
+
}
|
|
65
|
+
}
|
|
64
66
|
|
|
65
|
-
|
|
67
|
+
template<typename T>
|
|
68
|
+
Wrapper<std::shared_ptr<T>>::~Wrapper()
|
|
69
|
+
{
|
|
70
|
+
Registries::instance.instances.remove(this->get(this->rb_data_type_));
|
|
71
|
+
}
|
|
66
72
|
|
|
67
|
-
|
|
73
|
+
template<typename T>
|
|
74
|
+
void* Wrapper<std::shared_ptr<T>>::get(rb_data_type_t* requestedType)
|
|
75
|
+
{
|
|
76
|
+
if (rb_typeddata_inherited_p(this->rb_data_type_, requestedType))
|
|
77
|
+
{
|
|
78
|
+
return &this->data_;
|
|
68
79
|
}
|
|
69
|
-
|
|
80
|
+
else if (rb_typeddata_inherited_p(this->inner_rb_data_type_, requestedType))
|
|
81
|
+
{
|
|
82
|
+
return this->data_.get();
|
|
83
|
+
}
|
|
84
|
+
else
|
|
85
|
+
{
|
|
86
|
+
throw Exception(rb_eTypeError, "wrong argument type (expected %s)",
|
|
87
|
+
requestedType->wrap_struct_name);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
70
91
|
|
|
71
|
-
|
|
92
|
+
// --------- Type ---------
|
|
93
|
+
namespace Rice::detail
|
|
94
|
+
{
|
|
72
95
|
template<typename T>
|
|
73
|
-
struct Type<std::shared_ptr<T
|
|
96
|
+
struct Type<std::shared_ptr<T>>
|
|
74
97
|
{
|
|
75
98
|
static bool verify()
|
|
76
99
|
{
|
|
100
|
+
bool result = true;
|
|
77
101
|
if constexpr (std::is_fundamental_v<T>)
|
|
78
102
|
{
|
|
79
|
-
Type<Pointer<T>>::verify();
|
|
80
|
-
Type<Buffer<T>>::verify();
|
|
103
|
+
result = result && Type<Pointer<T>>::verify();
|
|
81
104
|
}
|
|
82
105
|
else
|
|
83
106
|
{
|
|
84
|
-
|
|
85
|
-
{
|
|
86
|
-
return false;
|
|
87
|
-
}
|
|
107
|
+
result = result && Type<T>::verify();
|
|
88
108
|
}
|
|
89
109
|
|
|
90
|
-
|
|
110
|
+
if (result)
|
|
111
|
+
{
|
|
112
|
+
define_shared_ptr<T>();
|
|
113
|
+
}
|
|
91
114
|
|
|
92
|
-
return
|
|
115
|
+
return result;
|
|
93
116
|
}
|
|
94
117
|
};
|
|
95
118
|
}
|