rice 4.3.3 → 4.6.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.
Files changed (237) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +86 -26
  3. data/CMakeLists.txt +31 -0
  4. data/CMakePresets.json +75 -0
  5. data/COPYING +3 -2
  6. data/FindRuby.cmake +437 -0
  7. data/README.md +7 -2
  8. data/Rakefile +12 -5
  9. data/include/rice/rice.hpp +9522 -4426
  10. data/include/rice/stl.hpp +2831 -1198
  11. data/lib/make_rice_headers.rb +79 -0
  12. data/lib/mkmf-rice.rb +40 -94
  13. data/lib/rice/version.rb +3 -0
  14. data/lib/rice.rb +1 -0
  15. data/lib/rubygems/builder.rb +11 -0
  16. data/lib/rubygems/cmake_builder.rb +113 -0
  17. data/lib/rubygems_plugin.rb +9 -0
  18. data/rice/Address_Registration_Guard.hpp +72 -3
  19. data/rice/Arg.hpp +26 -6
  20. data/rice/Arg.ipp +35 -2
  21. data/rice/Buffer.hpp +123 -0
  22. data/rice/Buffer.ipp +599 -0
  23. data/rice/Callback.hpp +21 -0
  24. data/rice/Callback.ipp +13 -0
  25. data/rice/Constructor.hpp +4 -27
  26. data/rice/Constructor.ipp +79 -0
  27. data/rice/Data_Object.hpp +73 -3
  28. data/rice/Data_Object.ipp +388 -96
  29. data/rice/Data_Type.hpp +214 -3
  30. data/rice/Data_Type.ipp +144 -67
  31. data/rice/Director.hpp +0 -2
  32. data/rice/Enum.hpp +4 -7
  33. data/rice/Enum.ipp +102 -55
  34. data/rice/Exception.hpp +62 -2
  35. data/rice/Exception.ipp +7 -12
  36. data/rice/Init.hpp +8 -0
  37. data/rice/Init.ipp +8 -0
  38. data/rice/JumpException.hpp +44 -0
  39. data/rice/JumpException.ipp +48 -0
  40. data/rice/MemoryView.hpp +11 -0
  41. data/rice/MemoryView.ipp +3 -0
  42. data/rice/Return.hpp +7 -27
  43. data/rice/Return.ipp +13 -13
  44. data/rice/cpp_api/Array.hpp +209 -0
  45. data/rice/cpp_api/Array.ipp +304 -0
  46. data/rice/cpp_api/Builtin_Object.hpp +31 -0
  47. data/rice/cpp_api/Builtin_Object.ipp +37 -0
  48. data/rice/cpp_api/Class.hpp +70 -0
  49. data/rice/cpp_api/Class.ipp +97 -0
  50. data/rice/cpp_api/Encoding.hpp +32 -0
  51. data/rice/cpp_api/Encoding.ipp +59 -0
  52. data/rice/cpp_api/Hash.hpp +194 -0
  53. data/rice/cpp_api/Hash.ipp +257 -0
  54. data/rice/{Identifier.hpp → cpp_api/Identifier.hpp} +2 -6
  55. data/rice/{Identifier.ipp → cpp_api/Identifier.ipp} +4 -2
  56. data/rice/cpp_api/Module.hpp +72 -0
  57. data/rice/cpp_api/Module.ipp +101 -0
  58. data/rice/cpp_api/Object.hpp +272 -0
  59. data/rice/cpp_api/Object.ipp +235 -0
  60. data/rice/cpp_api/String.hpp +74 -0
  61. data/rice/cpp_api/String.ipp +120 -0
  62. data/rice/cpp_api/Struct.hpp +113 -0
  63. data/rice/cpp_api/Struct.ipp +92 -0
  64. data/rice/cpp_api/Symbol.hpp +46 -0
  65. data/rice/cpp_api/Symbol.ipp +93 -0
  66. data/rice/cpp_api/shared_methods.hpp +134 -0
  67. data/rice/detail/DefaultHandler.hpp +12 -0
  68. data/rice/detail/DefaultHandler.ipp +8 -0
  69. data/rice/detail/HandlerRegistry.hpp +5 -35
  70. data/rice/detail/HandlerRegistry.ipp +7 -11
  71. data/rice/detail/InstanceRegistry.hpp +1 -4
  72. data/rice/detail/MethodInfo.hpp +12 -10
  73. data/rice/detail/MethodInfo.ipp +26 -21
  74. data/rice/detail/Native.hpp +33 -0
  75. data/rice/detail/Native.ipp +157 -0
  76. data/rice/detail/NativeAttributeGet.hpp +52 -0
  77. data/rice/detail/NativeAttributeGet.ipp +57 -0
  78. data/rice/detail/NativeAttributeSet.hpp +44 -0
  79. data/rice/detail/NativeAttributeSet.ipp +88 -0
  80. data/rice/detail/NativeCallbackFFI.hpp +55 -0
  81. data/rice/detail/NativeCallbackFFI.ipp +151 -0
  82. data/rice/detail/NativeCallbackSimple.hpp +30 -0
  83. data/rice/detail/NativeCallbackSimple.ipp +29 -0
  84. data/rice/detail/NativeFunction.hpp +33 -23
  85. data/rice/detail/NativeFunction.ipp +309 -70
  86. data/rice/detail/NativeIterator.hpp +9 -11
  87. data/rice/detail/NativeIterator.ipp +33 -31
  88. data/rice/detail/NativeRegistry.hpp +24 -15
  89. data/rice/detail/NativeRegistry.ipp +23 -48
  90. data/rice/detail/Proc.hpp +4 -0
  91. data/rice/detail/Proc.ipp +85 -0
  92. data/rice/detail/Registries.hpp +0 -7
  93. data/rice/detail/Registries.ipp +0 -18
  94. data/rice/detail/RubyFunction.hpp +0 -3
  95. data/rice/detail/RubyFunction.ipp +4 -8
  96. data/rice/detail/RubyType.hpp +16 -0
  97. data/rice/detail/RubyType.ipp +232 -0
  98. data/rice/detail/Type.hpp +7 -6
  99. data/rice/detail/Type.ipp +192 -45
  100. data/rice/detail/TypeRegistry.hpp +15 -7
  101. data/rice/detail/TypeRegistry.ipp +105 -12
  102. data/rice/detail/Wrapper.hpp +68 -32
  103. data/rice/detail/Wrapper.ipp +121 -109
  104. data/rice/detail/cpp_protect.hpp +5 -6
  105. data/rice/detail/default_allocation_func.ipp +0 -2
  106. data/rice/detail/from_ruby.hpp +38 -3
  107. data/rice/detail/from_ruby.ipp +1321 -492
  108. data/rice/detail/ruby.hpp +18 -0
  109. data/rice/detail/to_ruby.hpp +41 -3
  110. data/rice/detail/to_ruby.ipp +1424 -194
  111. data/rice/global_function.hpp +0 -4
  112. data/rice/global_function.ipp +0 -1
  113. data/rice/libc/file.hpp +11 -0
  114. data/rice/libc/file.ipp +32 -0
  115. data/rice/rice.hpp +116 -26
  116. data/rice/ruby_mark.hpp +4 -3
  117. data/rice/stl/complex.hpp +6 -0
  118. data/rice/stl/complex.ipp +93 -0
  119. data/rice/stl/exception.hpp +11 -0
  120. data/rice/stl/exception.ipp +29 -0
  121. data/rice/stl/exception_ptr.hpp +6 -0
  122. data/rice/stl/exception_ptr.ipp +27 -0
  123. data/rice/stl/map.hpp +12 -0
  124. data/rice/stl/map.ipp +469 -0
  125. data/rice/stl/monostate.hpp +6 -0
  126. data/rice/stl/monostate.ipp +80 -0
  127. data/rice/stl/multimap.hpp +14 -0
  128. data/rice/stl/multimap.ipp +448 -0
  129. data/rice/stl/optional.hpp +6 -0
  130. data/rice/stl/optional.ipp +118 -0
  131. data/rice/stl/pair.hpp +13 -0
  132. data/rice/stl/pair.ipp +155 -0
  133. data/rice/stl/reference_wrapper.hpp +6 -0
  134. data/rice/stl/reference_wrapper.ipp +41 -0
  135. data/rice/stl/set.hpp +12 -0
  136. data/rice/stl/set.ipp +495 -0
  137. data/rice/stl/shared_ptr.hpp +28 -0
  138. data/rice/stl/shared_ptr.ipp +224 -0
  139. data/rice/stl/string.hpp +6 -0
  140. data/rice/stl/string.ipp +158 -0
  141. data/rice/stl/string_view.hpp +6 -0
  142. data/rice/stl/string_view.ipp +65 -0
  143. data/rice/stl/tuple.hpp +6 -0
  144. data/rice/stl/tuple.ipp +128 -0
  145. data/rice/stl/type_index.hpp +6 -0
  146. data/rice/stl/type_index.ipp +30 -0
  147. data/rice/stl/type_info.hpp +6 -0
  148. data/rice/stl/type_info.ipp +29 -0
  149. data/rice/stl/unique_ptr.hpp +22 -0
  150. data/rice/stl/unique_ptr.ipp +139 -0
  151. data/rice/stl/unordered_map.hpp +12 -0
  152. data/rice/stl/unordered_map.ipp +469 -0
  153. data/rice/stl/variant.hpp +6 -0
  154. data/rice/stl/variant.ipp +242 -0
  155. data/rice/stl/vector.hpp +12 -0
  156. data/rice/stl/vector.ipp +590 -0
  157. data/rice/stl.hpp +11 -3
  158. data/rice/traits/attribute_traits.hpp +26 -0
  159. data/rice/traits/function_traits.hpp +95 -0
  160. data/rice/traits/method_traits.hpp +47 -0
  161. data/rice/traits/rice_traits.hpp +160 -0
  162. data/rice.gemspec +85 -0
  163. data/test/embed_ruby.cpp +7 -1
  164. data/test/extconf.rb +2 -0
  165. data/test/test_Address_Registration_Guard.cpp +5 -0
  166. data/test/test_Array.cpp +18 -4
  167. data/test/test_Attribute.cpp +136 -21
  168. data/test/test_Buffer.cpp +285 -0
  169. data/test/test_Builtin_Object.cpp +5 -0
  170. data/test/test_Callback.cpp +230 -0
  171. data/test/test_Class.cpp +5 -31
  172. data/test/test_Constructor.cpp +69 -6
  173. data/test/test_Data_Object.cpp +97 -38
  174. data/test/test_Data_Type.cpp +470 -65
  175. data/test/test_Director.cpp +17 -8
  176. data/test/test_Enum.cpp +155 -40
  177. data/test/test_Exception.cpp +235 -0
  178. data/test/test_File.cpp +70 -0
  179. data/test/test_From_Ruby.cpp +609 -0
  180. data/test/test_Hash.cpp +5 -0
  181. data/test/test_Identifier.cpp +5 -0
  182. data/test/test_Inheritance.cpp +6 -1
  183. data/test/test_Iterator.cpp +6 -1
  184. data/test/test_Jump_Exception.cpp +23 -0
  185. data/test/test_Keep_Alive.cpp +13 -19
  186. data/test/test_Keep_Alive_No_Wrapper.cpp +5 -1
  187. data/test/test_Memory_Management.cpp +5 -0
  188. data/test/test_Module.cpp +128 -67
  189. data/test/test_Native_Registry.cpp +2 -34
  190. data/test/test_Object.cpp +5 -0
  191. data/test/test_Overloads.cpp +806 -0
  192. data/test/test_Ownership.cpp +160 -54
  193. data/test/test_Proc.cpp +44 -0
  194. data/test/test_Self.cpp +9 -4
  195. data/test/test_Stl_Exception.cpp +109 -0
  196. data/test/test_Stl_Map.cpp +54 -42
  197. data/test/test_Stl_Multimap.cpp +693 -0
  198. data/test/test_Stl_Optional.cpp +5 -0
  199. data/test/test_Stl_Pair.cpp +14 -9
  200. data/test/test_Stl_Reference_Wrapper.cpp +9 -2
  201. data/test/test_Stl_Set.cpp +790 -0
  202. data/test/test_Stl_SharedPtr.cpp +458 -0
  203. data/test/test_Stl_String.cpp +5 -0
  204. data/test/test_Stl_String_View.cpp +5 -0
  205. data/test/test_Stl_Tuple.cpp +116 -0
  206. data/test/test_Stl_Type.cpp +147 -0
  207. data/test/test_Stl_UniquePtr.cpp +202 -0
  208. data/test/test_Stl_Unordered_Map.cpp +43 -38
  209. data/test/test_Stl_Variant.cpp +217 -84
  210. data/test/test_Stl_Vector.cpp +306 -58
  211. data/test/test_String.cpp +5 -0
  212. data/test/test_Struct.cpp +5 -0
  213. data/test/test_Symbol.cpp +5 -0
  214. data/test/test_Template.cpp +192 -0
  215. data/test/test_To_Ruby.cpp +524 -0
  216. data/test/test_Tracking.cpp +1 -0
  217. data/test/test_Type.cpp +171 -0
  218. data/test/test_global_functions.cpp +67 -7
  219. data/test/unittest.cpp +8 -0
  220. metadata +127 -26
  221. data/lib/version.rb +0 -3
  222. data/rice/Address_Registration_Guard_defn.hpp +0 -79
  223. data/rice/Data_Object_defn.hpp +0 -84
  224. data/rice/Data_Type_defn.hpp +0 -190
  225. data/rice/Exception_defn.hpp +0 -68
  226. data/rice/HandlerRegistration.hpp +0 -15
  227. data/rice/detail/ExceptionHandler.hpp +0 -8
  228. data/rice/detail/ExceptionHandler.ipp +0 -28
  229. data/rice/detail/ExceptionHandler_defn.hpp +0 -77
  230. data/rice/detail/Jump_Tag.hpp +0 -21
  231. data/rice/detail/NativeAttribute.hpp +0 -64
  232. data/rice/detail/NativeAttribute.ipp +0 -112
  233. data/rice/detail/from_ruby_defn.hpp +0 -38
  234. data/rice/detail/to_ruby_defn.hpp +0 -48
  235. data/test/test_Jump_Tag.cpp +0 -17
  236. data/test/test_Stl_SmartPointer.cpp +0 -283
  237. data/test/test_To_From_Ruby.cpp +0 -399
@@ -1,8 +1,8 @@
1
+ #include <iostream>
1
2
  #include <stdexcept>
3
+ #include <sstream>
4
+ #include <typeindex>
2
5
 
3
- #include "ruby.hpp"
4
- #include "../traits/rice_traits.hpp"
5
- #include "Type.hpp"
6
6
 
7
7
  namespace Rice::detail
8
8
  {
@@ -13,6 +13,22 @@ namespace Rice::detail
13
13
  registry_[key] = std::pair(klass, rbType);
14
14
  }
15
15
 
16
+ /* Special case void. Rice defines classes using the class name not a pointer to the
17
+ class. Thus define_class<void> is more consistent with Rice then
18
+ define_class<void*>. However, the types of void and void* are different so we need
19
+ this special case.
20
+
21
+ It is possible to support define_class<void*>, but it requires changing the static
22
+ assertions on Data_Type and Data_Object and thus seems less desirable (and less
23
+ consistent as mentioned above).*/
24
+ template <>
25
+ inline void TypeRegistry::add<void>(VALUE klass, rb_data_type_t* rbType)
26
+ {
27
+ // The special case, use void*
28
+ std::type_index key(typeid(void*));
29
+ registry_[key] = std::pair(klass, rbType);
30
+ }
31
+
16
32
  template <typename T>
17
33
  inline void TypeRegistry::remove()
18
34
  {
@@ -29,14 +45,45 @@ namespace Rice::detail
29
45
  }
30
46
 
31
47
  template <typename T>
32
- inline bool TypeRegistry::verifyDefined()
48
+ std::pair<VALUE, rb_data_type_t*> TypeRegistry::getType()
33
49
  {
34
- if (!isDefined<T>())
50
+ std::type_index key(typeid(T));
51
+ auto iter = registry_.find(key);
52
+ if (iter != registry_.end())
35
53
  {
36
- std::string message = "Type is not defined with Rice: " + detail::typeName(typeid(T));
37
- throw std::invalid_argument(message);
54
+ return iter->second;
55
+ }
56
+ else
57
+ {
58
+ this->raiseUnverifiedType(typeid(T).name());
59
+ // Make compiler happy
60
+ return std::make_pair(Qnil, nullptr);
61
+ }
62
+ }
63
+
64
+ // Special case void. See comment for add above.
65
+ template <>
66
+ inline bool TypeRegistry::isDefined<void>()
67
+ {
68
+ std::type_index key(typeid(void*));
69
+ auto iter = registry_.find(key);
70
+ return iter != registry_.end();
71
+ }
72
+
73
+ template <typename T>
74
+ inline bool TypeRegistry::verify()
75
+ {
76
+ if (isDefined<T>())
77
+ {
78
+ return true;
79
+ }
80
+ else
81
+ {
82
+ const std::type_info& typeInfo = typeid(T);
83
+ std::type_index key(typeInfo);
84
+ this->unverified_.insert(key);
85
+ return false;
38
86
  }
39
- return true;
40
87
  }
41
88
 
42
89
  inline std::optional<std::pair<VALUE, rb_data_type_t*>> TypeRegistry::lookup(const std::type_info& typeInfo)
@@ -68,14 +115,60 @@ namespace Rice::detail
68
115
  // If not, then we are willing to accept an ancestor class specified by T. This is needed
69
116
  // to support Directors. Classes inherited from Directors are never actually registered
70
117
  // with Rice - and what we really want it to return the C++ class they inherit from.
71
- result = lookup(typeid(T));
118
+ const std::type_info& typeInfo = typeid(T);
119
+ result = lookup(typeInfo);
72
120
  if (result)
73
121
  {
74
122
  return result.value();
75
123
  }
76
124
 
77
- // Give up!
78
- std::string message = "Type " + typeName(typeid(object)) + " is not registered";
79
- throw std::runtime_error(message.c_str());
125
+ raiseUnverifiedType(detail::typeName(typeInfo));
126
+ // Make the compiler happy
127
+ return std::pair<VALUE, rb_data_type_t*>(Qnil, nullptr);
128
+ }
129
+
130
+ inline void TypeRegistry::validateTypes()
131
+ {
132
+ // Loop over the unverified types and delete each on that is found in the registry
133
+ // the registry and raise an exception for the first one that is not
134
+ for (auto iter = this->unverified_.begin(); iter != this->unverified_.end(); )
135
+ {
136
+ const std::type_index& typeIndex = *iter;
137
+ bool isDefined = this->registry_.find(typeIndex) != this->registry_.end();
138
+ if (isDefined)
139
+ {
140
+ iter = this->unverified_.erase(iter);
141
+ }
142
+ else
143
+ {
144
+ iter++;
145
+ }
146
+ }
147
+
148
+ if (this->unverified_.empty())
149
+ {
150
+ return;
151
+ }
152
+
153
+ std::stringstream stream;
154
+ stream << "The following types are not registered with Rice:" << "\n";
155
+
156
+ for (const std::type_index& typeIndex : this->unverified_)
157
+ {
158
+ stream << " " << typeName(typeIndex) << "\n";
159
+ }
160
+
161
+ throw std::invalid_argument(stream.str());
162
+ }
163
+
164
+ inline void TypeRegistry::clearUnverifiedTypes()
165
+ {
166
+ this->unverified_.clear();
167
+ }
168
+
169
+ inline void TypeRegistry::raiseUnverifiedType(const std::string& typeName)
170
+ {
171
+ std::string message = "Type is not registered with Rice: " + typeName;
172
+ throw std::invalid_argument(message);
80
173
  }
81
174
  }
@@ -1,49 +1,85 @@
1
1
  #ifndef Rice__detail__Wrapper__hpp_
2
2
  #define Rice__detail__Wrapper__hpp_
3
3
 
4
- #include "ruby.hpp"
5
-
6
- namespace Rice
7
- {
8
- namespace detail
4
+ namespace Rice::detail
9
5
  {
6
+ class WrapperBase
7
+ {
8
+ public:
9
+ WrapperBase() = default;
10
+ virtual ~WrapperBase() = default;
11
+ virtual void* get() = 0;
12
+ bool isConst();
10
13
 
11
- class Wrapper
12
- {
13
- public:
14
- virtual ~Wrapper() = default;
15
- virtual void* get() = 0;
14
+ void ruby_mark();
15
+ void addKeepAlive(VALUE value);
16
+ void setOwner(bool value);
16
17
 
17
- void ruby_mark();
18
- void addKeepAlive(VALUE value);
18
+ protected:
19
+ bool isOwner_ = false;
20
+ bool isConst_ = false;
19
21
 
20
- private:
21
- // We use a vector for speed and memory locality versus a set which does
22
- // not scale well when getting to tens of thousands of objects (not expecting
23
- // that to happen...but just in case)
24
- std::vector<VALUE> keepAlive_;
25
- };
22
+ private:
23
+ // We use a vector for speed and memory locality versus a set which does
24
+ // not scale well when getting to tens of thousands of objects (not expecting
25
+ // that to happen...but just in case)
26
+ std::vector<VALUE> keepAlive_;
27
+ };
26
28
 
27
- template <typename T, typename Wrapper_T = void>
28
- VALUE wrap(VALUE klass, rb_data_type_t* rb_type, T& data, bool isOwner);
29
+ template <typename T>
30
+ class Wrapper : public WrapperBase
31
+ {
32
+ public:
33
+ Wrapper(T& data);
34
+ Wrapper(T&& data);
35
+ ~Wrapper();
36
+ void* get() override;
29
37
 
30
- template <typename T, typename Wrapper_T = void>
31
- VALUE wrap(VALUE klass, rb_data_type_t* rb_type, T* data, bool isOwner);
38
+ private:
39
+ T data_;
40
+ };
32
41
 
33
- template <typename T>
34
- T* unwrap(VALUE value, rb_data_type_t* rb_type);
42
+ template<typename T>
43
+ class Wrapper<T&> : public WrapperBase
44
+ {
45
+ public:
46
+ Wrapper(T& data);
47
+ ~Wrapper();
48
+ void* get() override;
35
49
 
36
- Wrapper* getWrapper(VALUE value, rb_data_type_t* rb_type);
50
+ private:
51
+ T& data_;
52
+ };
37
53
 
38
- template <typename T>
39
- void replace(VALUE value, rb_data_type_t* rb_type, T* data, bool isOwner);
54
+ template <typename T>
55
+ class Wrapper<T*> : public WrapperBase
56
+ {
57
+ public:
58
+ Wrapper(T* data, bool isOwner);
59
+ ~Wrapper();
60
+ void* get() override;
40
61
 
41
- Wrapper* getWrapper(VALUE value);
62
+ private:
63
+ T* data_ = nullptr;
64
+ };
42
65
 
43
- } // namespace detail
44
- } // namespace Rice
66
+ // ---- Helper Functions ---------
67
+ template <typename T>
68
+ void wrapConstructed(VALUE value, rb_data_type_t* rb_data_type, T* data, bool isOwner);
45
69
 
46
- #include "Wrapper.ipp"
70
+ template <typename T>
71
+ VALUE wrap(VALUE klass, rb_data_type_t* rb_data_type, T& data, bool isOwner);
47
72
 
48
- #endif // Rice__detail__Wrapper__hpp_
73
+ template <typename T>
74
+ VALUE wrap(VALUE klass, rb_data_type_t* rb_data_type, T* data, bool isOwner);
49
75
 
76
+ template <typename T>
77
+ T* unwrap(VALUE value, rb_data_type_t* rb_data_type, bool takeOwnership);
78
+
79
+ template <typename Wrapper_T = WrapperBase>
80
+ Wrapper_T* getWrapper(VALUE value, rb_data_type_t* rb_data_type);
81
+
82
+ WrapperBase* getWrapper(VALUE value);
83
+ }
84
+ #endif // Rice__detail__Wrapper__hpp_
85
+
@@ -1,9 +1,13 @@
1
1
  #include <memory>
2
- #include "InstanceRegistry.hpp"
3
2
 
4
3
  namespace Rice::detail
5
4
  {
6
- inline void Wrapper::ruby_mark()
5
+ inline bool WrapperBase::isConst()
6
+ {
7
+ return this->isConst_;
8
+ }
9
+
10
+ inline void WrapperBase::ruby_mark()
7
11
  {
8
12
  for (VALUE value : this->keepAlive_)
9
13
  {
@@ -11,118 +15,122 @@ namespace Rice::detail
11
15
  }
12
16
  }
13
17
 
14
- inline void Wrapper::addKeepAlive(VALUE value)
18
+ inline void WrapperBase::addKeepAlive(VALUE value)
15
19
  {
16
20
  this->keepAlive_.push_back(value);
17
21
  }
18
22
 
19
- template <typename T>
20
- class WrapperValue : public Wrapper
23
+ inline void WrapperBase::setOwner(bool value)
21
24
  {
22
- public:
23
- WrapperValue(T& data): data_(std::move(data))
24
- {
25
- }
25
+ this->isOwner_ = value;
26
+ }
26
27
 
27
- ~WrapperValue()
28
- {
29
- Registries::instance.instances.remove(this->get());
30
- }
28
+ // ---- Wrapper -----
29
+ template <typename T>
30
+ inline Wrapper<T>::Wrapper(T& data): data_(data)
31
+ {
32
+ }
31
33
 
32
- void* get() override
33
- {
34
- return (void*)&this->data_;
35
- }
34
+ template <typename T>
35
+ inline Wrapper<T>::Wrapper(T&& data) : data_(std::move(data))
36
+ {
37
+ }
36
38
 
37
- private:
38
- T data_;
39
- };
39
+ template <typename T>
40
+ inline Wrapper<T>::~Wrapper()
41
+ {
42
+ Registries::instance.instances.remove(this->get());
43
+ }
40
44
 
41
45
  template <typename T>
42
- class WrapperReference : public Wrapper
46
+ inline void* Wrapper<T>::Wrapper::get()
43
47
  {
44
- public:
45
- WrapperReference(T& data): data_(data)
46
- {
47
- }
48
+ return (void*)&this->data_;
49
+ }
48
50
 
49
- ~WrapperReference()
50
- {
51
- Registries::instance.instances.remove(this->get());
52
- }
51
+ // ---- Wrapper& -----
52
+ template <typename T>
53
+ inline Wrapper<T&>::Wrapper(T& data): data_(data)
54
+ {
55
+ this->isConst_ = std::is_const_v<std::remove_reference_t<T>>;
56
+ }
53
57
 
54
- void* get() override
55
- {
56
- return (void*)&this->data_;
57
- }
58
+ template <typename T>
59
+ inline Wrapper<T&>::~Wrapper()
60
+ {
61
+ Registries::instance.instances.remove(this->get());
62
+ }
58
63
 
59
- private:
60
- T& data_;
61
- };
64
+ template <typename T>
65
+ inline void* Wrapper<T&>::get()
66
+ {
67
+ return (void*)&this->data_;
68
+ }
62
69
 
70
+ // ---- Wrapper* -----
63
71
  template <typename T>
64
- class WrapperPointer : public Wrapper
72
+ inline Wrapper<T*>::Wrapper(T* data, bool isOwner) : data_(data)
65
73
  {
66
- public:
67
- WrapperPointer(T* data, bool isOwner) : data_(data), isOwner_(isOwner)
68
- {
69
- }
74
+ this->isOwner_ = isOwner;
75
+ this->isConst_ = std::is_const_v<std::remove_pointer_t<T>>;
76
+ }
70
77
 
71
- ~WrapperPointer()
78
+ template <typename T>
79
+ inline Wrapper<T*>::~Wrapper()
80
+ {
81
+ Registries::instance.instances.remove(this->get());
82
+ if constexpr (std::is_destructible_v<T>)
72
83
  {
73
- Registries::instance.instances.remove(this->get());
74
-
75
84
  if (this->isOwner_)
76
85
  {
77
86
  delete this->data_;
78
87
  }
79
88
  }
89
+ }
80
90
 
81
- void* get() override
82
- {
83
- return (void*)this->data_;
84
- }
85
-
86
- private:
87
- T* data_ = nullptr;
88
- bool isOwner_ = false;
89
- };
91
+ template <typename T>
92
+ inline void* Wrapper<T*>::get()
93
+ {
94
+ return (void*)this->data_;
95
+ }
90
96
 
91
97
  // ---- Helper Functions -------
92
- template <typename T, typename Wrapper_T>
93
- inline VALUE wrap(VALUE klass, rb_data_type_t* rb_type, T& data, bool isOwner)
98
+ template <typename T>
99
+ inline VALUE wrap(VALUE klass, rb_data_type_t* rb_data_type, T& data, bool isOwner)
94
100
  {
95
101
  VALUE result = Registries::instance.instances.lookup(&data);
96
102
 
97
103
  if (result != Qnil)
98
104
  return result;
99
105
 
100
- Wrapper* wrapper = nullptr;
106
+ WrapperBase* wrapper = nullptr;
101
107
 
102
- // Is this a pointer but cannot be copied? For example a std::unique_ptr
103
- if constexpr (!std::is_void_v<Wrapper_T> && !std::is_copy_constructible_v<Wrapper_T>)
108
+ // If Ruby is not the owner then wrap the reference
109
+ if (!isOwner)
104
110
  {
105
- wrapper = new Wrapper_T(std::move(data));
106
- result = TypedData_Wrap_Struct(klass, rb_type, wrapper);
111
+ wrapper = new Wrapper<T&>(data);
112
+ result = TypedData_Wrap_Struct(klass, rb_data_type, wrapper);
107
113
  }
108
- // Is this a pointer or smart pointer like std::shared_ptr
109
- else if constexpr (!std::is_void_v<Wrapper_T>)
114
+
115
+ // Ruby is the owner so copy data
116
+ else if constexpr (std::is_copy_constructible_v<T>)
110
117
  {
111
- wrapper = new Wrapper_T(data);
112
- result = TypedData_Wrap_Struct(klass, rb_type, wrapper);
118
+ wrapper = new Wrapper<T>(data);
119
+ result = TypedData_Wrap_Struct(klass, rb_data_type, wrapper);
113
120
  }
114
- // Is this a pointer and it cannot copied? This is for std::unique_ptr
115
- // If ruby is the owner than copy the object
116
- else if (isOwner)
121
+
122
+ // Ruby is the owner so move data
123
+ else if constexpr (std::is_move_constructible_v<T>)
117
124
  {
118
- wrapper = new WrapperValue<T>(data);
119
- result = TypedData_Wrap_Struct(klass, rb_type, wrapper);
125
+ wrapper = new Wrapper<T>(std::forward<T>(data));
126
+ result = TypedData_Wrap_Struct(klass, rb_data_type, wrapper);
120
127
  }
121
- // Ruby is not the owner so just wrap the reference
128
+
122
129
  else
123
130
  {
124
- wrapper = new WrapperReference<T>(data);
125
- result = TypedData_Wrap_Struct(klass, rb_type, wrapper);
131
+ std::string message = "Rice was directed to take ownership of a C++ object but it does not have an accessible copy or move constructor. Type: " +
132
+ typeName(typeid(T));
133
+ throw std::runtime_error(message);
126
134
  }
127
135
 
128
136
  Registries::instance.instances.add(wrapper->get(), result);
@@ -130,35 +138,31 @@ namespace Rice::detail
130
138
  return result;
131
139
  };
132
140
 
133
- template <typename T, typename Wrapper_T>
134
- inline VALUE wrap(VALUE klass, rb_data_type_t* rb_type, T* data, bool isOwner)
141
+ template <typename T>
142
+ inline VALUE wrap(VALUE klass, rb_data_type_t* rb_data_type, T* data, bool isOwner)
135
143
  {
136
144
  VALUE result = Registries::instance.instances.lookup(data);
137
145
 
138
146
  if (result != Qnil)
139
147
  return result;
140
148
 
141
- Wrapper* wrapper = nullptr;
142
-
143
- if constexpr (!std::is_void_v<Wrapper_T>)
144
- {
145
- wrapper = new Wrapper_T(data);
146
- result = TypedData_Wrap_Struct(klass, rb_type, wrapper);
147
- }
148
- else
149
- {
150
- wrapper = new WrapperPointer<T>(data, isOwner);
151
- result = TypedData_Wrap_Struct(klass, rb_type, wrapper);
152
- }
149
+ WrapperBase* wrapper = new Wrapper<T*>(data, isOwner);
150
+ result = TypedData_Wrap_Struct(klass, rb_data_type, wrapper);
153
151
 
154
152
  Registries::instance.instances.add(wrapper->get(), result);
155
153
  return result;
156
154
  };
157
155
 
158
156
  template <typename T>
159
- inline T* unwrap(VALUE value, rb_data_type_t* rb_type)
157
+ inline T* unwrap(VALUE value, rb_data_type_t* rb_data_type, bool takeOwnership)
160
158
  {
161
- Wrapper* wrapper = getWrapper(value, rb_type);
159
+ if (rb_type(value) != RUBY_T_DATA)
160
+ {
161
+ std::string message = "The provided Ruby object does not wrap a C++ object";
162
+ throw std::runtime_error(message);
163
+ }
164
+
165
+ WrapperBase* wrapper = getWrapper(value, rb_data_type);
162
166
 
163
167
  if (wrapper == nullptr)
164
168
  {
@@ -169,43 +173,51 @@ namespace Rice::detail
169
173
  throw std::runtime_error(message);
170
174
  }
171
175
 
176
+ if (takeOwnership)
177
+ wrapper->setOwner(false);
178
+
172
179
  return static_cast<T*>(wrapper->get());
173
180
  }
174
181
 
175
- inline Wrapper* getWrapper(VALUE value, rb_data_type_t* rb_type)
182
+ template <typename Wrapper_T>
183
+ inline Wrapper_T* getWrapper(VALUE value, rb_data_type_t* rb_data_type)
184
+ {
185
+ WrapperBase* wrapper = nullptr;
186
+ TypedData_Get_Struct(value, WrapperBase, rb_data_type, wrapper);
187
+ return dynamic_cast<Wrapper_T*>(wrapper);
188
+ }
189
+
190
+ inline WrapperBase* getWrapper(VALUE value)
176
191
  {
177
- Wrapper* wrapper = nullptr;
178
- TypedData_Get_Struct(value, Wrapper, rb_type, wrapper);
179
- return wrapper;
192
+ // Turn off spurious warning on g++ 12
193
+ #if defined(__GNUC__) || defined(__clang__)
194
+ #pragma GCC diagnostic push
195
+ #pragma GCC diagnostic ignored "-Warray-bounds"
196
+ #endif
197
+
198
+ return RTYPEDDATA_P(value) ? static_cast<WrapperBase*>(RTYPEDDATA_DATA(value)) : nullptr;
199
+
200
+ #if defined(__GNUC__) || defined(__clang__)
201
+ #pragma GCC diagnostic pop
202
+ #endif
180
203
  }
181
204
 
182
205
  template <typename T>
183
- inline void replace(VALUE value, rb_data_type_t* rb_type, T* data, bool isOwner)
206
+ inline void wrapConstructed(VALUE value, rb_data_type_t* rb_data_type, T* data, bool isOwner)
184
207
  {
185
- WrapperPointer<T>* wrapper = nullptr;
186
- TypedData_Get_Struct(value, WrapperPointer<T>, rb_type, wrapper);
208
+ using Wrapper_T = Wrapper<T*>;
209
+
210
+ Wrapper_T* wrapper = nullptr;
211
+ TypedData_Get_Struct(value, Wrapper_T, rb_data_type, wrapper);
187
212
  if (wrapper)
188
213
  {
189
214
  Registries::instance.instances.remove(wrapper->get());
190
215
  delete wrapper;
191
216
  }
192
217
 
193
- wrapper = new WrapperPointer<T>(data, isOwner);
218
+ wrapper = new Wrapper_T(data, true);
194
219
  RTYPEDDATA_DATA(value) = wrapper;
195
220
 
196
221
  Registries::instance.instances.add(data, value);
197
222
  }
198
-
199
- inline Wrapper* getWrapper(VALUE value)
200
- {
201
- // Turn off spurious warning on g++ 12
202
- #ifdef __GNUC__
203
- #pragma GCC diagnostic push
204
- #pragma GCC diagnostic ignored "-Warray-bounds"
205
- #endif
206
- return RTYPEDDATA_P(value) ? static_cast<Wrapper*>(RTYPEDDATA_DATA(value)) : nullptr;
207
- #ifdef __GNUC__
208
- #pragma GCC diagnostic pop
209
- #endif
210
- }
211
223
  } // namespace
@@ -14,8 +14,6 @@
14
14
  #error "no filesystem include found :'("
15
15
  #endif
16
16
 
17
- #include "Jump_Tag.hpp"
18
- #include "../Exception_defn.hpp"
19
17
 
20
18
  namespace Rice::detail
21
19
  {
@@ -30,13 +28,14 @@ namespace Rice::detail
30
28
  {
31
29
  try
32
30
  {
33
- detail::Registries::instance.handlers.handler()->handle();
31
+ std::function<void()> handler = detail::Registries::instance.handlers.handler();
32
+ handler();
34
33
  }
35
34
  catch (::Rice::Exception const& ex)
36
35
  {
37
36
  rb_exc_raise(ex.value());
38
37
  }
39
- catch (::Rice::Jump_Tag const& ex)
38
+ catch (::Rice::JumpException const& ex)
40
39
  {
41
40
  rb_jump_tag(ex.tag);
42
41
  }
@@ -61,11 +60,11 @@ namespace Rice::detail
61
60
  }
62
61
  catch (std::length_error const& ex)
63
62
  {
64
- rb_exc_raise(rb_exc_new2(rb_eRuntimeError, ex.what()));
63
+ rb_exc_raise(rb_exc_new2(rb_eIndexError, ex.what()));
65
64
  }
66
65
  catch (std::out_of_range const& ex)
67
66
  {
68
- rb_exc_raise(rb_exc_new2(rb_eRangeError, ex.what()));
67
+ rb_exc_raise(rb_exc_new2(rb_eIndexError, ex.what()));
69
68
  }
70
69
  catch (std::overflow_error const& ex)
71
70
  {
@@ -1,5 +1,3 @@
1
- #include "../Data_Object.hpp"
2
-
3
1
  namespace Rice::detail
4
2
  {
5
3
  template<typename T>
@@ -1,8 +1,43 @@
1
1
  #ifndef Rice__detail__from_ruby__hpp_
2
2
  #define Rice__detail__from_ruby__hpp_
3
3
 
4
- #include "from_ruby_defn.hpp"
5
- #include "from_ruby.ipp"
4
+ namespace Rice::detail
5
+ {
6
+ //! Convert a Ruby object to C++.
7
+ /*! If the Ruby object can be converted to an immediate value, returns a
8
+ * copy of the Ruby object. If the Ruby object is holding a C++
9
+ * object and the type specified is a pointer to that type, returns a
10
+ * pointer to that object.
11
+ *
12
+ * Conversions from ruby to a pointer type are automatically generated
13
+ * when a type is bound using Data_Type. If no conversion exists an
14
+ * exception is thrown.
15
+ *
16
+ * \param T the C++ type to which to convert.
17
+ * \param x the Ruby object to convert.
18
+ * \return a C++ representation of the Ruby object.
19
+ *
20
+ * Example:
21
+ * \code
22
+ * Object x = INT2NUM(42);
23
+ * std::cout << From_Ruby<int>::convert(x);
24
+ *
25
+ * Data_Object<Foo> foo(new Foo);
26
+ * std::cout << *From_Ruby<Foo *>(foo) << std::endl;
27
+ * \endcode
28
+ */
6
29
 
7
- #endif // Rice__detail__from_ruby__hpp_
30
+ template <typename T>
31
+ class From_Ruby;
8
32
 
33
+ enum class Convertible: uint8_t
34
+ {
35
+ None = 0b0000,
36
+ Narrow = 0b0001,
37
+ Cast = 0b0011,
38
+ Const = 0b0111,
39
+ Exact = 0b1111
40
+ };
41
+ }
42
+
43
+ #endif // Rice__detail__From_Ruby2__hpp_