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.
@@ -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, "*");
@@ -6,9 +6,9 @@ namespace Rice::detail
6
6
  class WrapperBase
7
7
  {
8
8
  public:
9
- WrapperBase() = default;
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;
@@ -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>::Wrapper::get()
51
+ inline void* Wrapper<T>::get(rb_data_type_t* requestedType)
48
52
  {
49
- return (void*)&this->data_;
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
- return (void*)&this->data_;
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
- return (void*)this->data_;
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
- return (void*)this->data_;
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 (rb_type(value) != RUBY_T_DATA)
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 = getWrapper(value, rb_data_type);
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
- detail::protect(rb_obj_classname, value), "wrapped C++ object");
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
- } // namespace
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
  }
@@ -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_
@@ -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>(rb_mStd, id);
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
- // std::shared_ptr<void> cannot be constructed from void* because void is incomplete
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
- result.
36
- define_method("get", &SharedPtr_T::get).
37
- define_method("use_count", &SharedPtr_T::use_count).
38
- define_method("empty?", &SharedPtr_T::operator bool);
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
- // --------- Type/To_Ruby/From_Ruby ---------
48
+ // --------- Wrapper ---------
45
49
  namespace Rice::detail
46
50
  {
47
51
  template<typename T>
48
- struct Type<std::shared_ptr<T>>
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
- static bool verify()
55
+ using Intrinsic_T = intrinsic_type<T>;
56
+
57
+ if constexpr (std::is_fundamental_v<Intrinsic_T>)
51
58
  {
52
- if constexpr (std::is_fundamental_v<T>)
53
- {
54
- Type<Pointer<T>>::verify();
55
- Type<Buffer<T>>::verify();
56
- }
57
- else
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
- define_shared_ptr<T>();
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
- return true;
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
- // Specialization for array types std::shared_ptr<T[]>
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
- if (!Type<intrinsic_type<T>>::verify())
85
- {
86
- return false;
87
- }
107
+ result = result && Type<T>::verify();
88
108
  }
89
109
 
90
- define_shared_ptr<T[]>();
110
+ if (result)
111
+ {
112
+ define_shared_ptr<T>();
113
+ }
91
114
 
92
- return true;
115
+ return result;
93
116
  }
94
117
  };
95
118
  }