rice 4.0.4 → 4.1.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 (94) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +30 -0
  3. data/Rakefile +1 -1
  4. data/include/rice/rice.hpp +2596 -1771
  5. data/include/rice/stl.hpp +1580 -271
  6. data/lib/mkmf-rice.rb +5 -2
  7. data/lib/version.rb +1 -1
  8. data/rice/Arg.hpp +6 -6
  9. data/rice/Arg.ipp +8 -9
  10. data/rice/Constructor.hpp +2 -2
  11. data/rice/Data_Object.ipp +69 -15
  12. data/rice/Data_Object_defn.hpp +1 -15
  13. data/rice/Data_Type.ipp +56 -86
  14. data/rice/Data_Type_defn.hpp +14 -17
  15. data/rice/Director.hpp +0 -1
  16. data/rice/Enum.ipp +31 -22
  17. data/rice/Exception.ipp +2 -3
  18. data/rice/Exception_defn.hpp +5 -5
  19. data/rice/HandlerRegistration.hpp +15 -0
  20. data/rice/Return.hpp +5 -4
  21. data/rice/Return.ipp +8 -3
  22. data/rice/detail/ExceptionHandler.hpp +8 -0
  23. data/rice/detail/ExceptionHandler.ipp +28 -0
  24. data/rice/detail/{Exception_Handler_defn.hpp → ExceptionHandler_defn.hpp} +17 -21
  25. data/rice/detail/HandlerRegistry.hpp +51 -0
  26. data/rice/detail/HandlerRegistry.ipp +20 -0
  27. data/rice/detail/InstanceRegistry.hpp +34 -0
  28. data/rice/detail/InstanceRegistry.ipp +50 -0
  29. data/rice/detail/MethodInfo.ipp +1 -1
  30. data/rice/detail/NativeAttribute.hpp +26 -15
  31. data/rice/detail/NativeAttribute.ipp +76 -47
  32. data/rice/detail/NativeFunction.hpp +60 -13
  33. data/rice/detail/NativeFunction.ipp +103 -85
  34. data/rice/detail/NativeIterator.hpp +49 -0
  35. data/rice/detail/NativeIterator.ipp +102 -0
  36. data/rice/detail/NativeRegistry.hpp +31 -0
  37. data/rice/detail/{method_data.ipp → NativeRegistry.ipp} +20 -16
  38. data/rice/detail/Registries.hpp +26 -0
  39. data/rice/detail/Registries.ipp +23 -0
  40. data/rice/detail/RubyFunction.hpp +6 -11
  41. data/rice/detail/RubyFunction.ipp +10 -22
  42. data/rice/detail/Type.hpp +1 -1
  43. data/rice/detail/Type.ipp +2 -2
  44. data/rice/detail/TypeRegistry.hpp +8 -11
  45. data/rice/detail/TypeRegistry.ipp +3 -28
  46. data/rice/detail/Wrapper.hpp +0 -2
  47. data/rice/detail/Wrapper.ipp +73 -23
  48. data/rice/detail/cpp_protect.hpp +93 -0
  49. data/rice/detail/default_allocation_func.ipp +1 -1
  50. data/rice/detail/from_ruby.ipp +206 -2
  51. data/rice/detail/to_ruby.ipp +39 -5
  52. data/rice/detail/to_ruby_defn.hpp +1 -1
  53. data/rice/forward_declares.ipp +6 -0
  54. data/rice/global_function.hpp +0 -4
  55. data/rice/global_function.ipp +0 -6
  56. data/rice/rice.hpp +29 -24
  57. data/rice/stl.hpp +6 -1
  58. data/test/embed_ruby.cpp +0 -15
  59. data/test/test_Array.cpp +20 -24
  60. data/test/test_Class.cpp +8 -47
  61. data/test/test_Constructor.cpp +0 -2
  62. data/test/test_Data_Object.cpp +25 -11
  63. data/test/test_Data_Type.cpp +124 -28
  64. data/test/test_Director.cpp +12 -13
  65. data/test/test_Enum.cpp +65 -26
  66. data/test/test_Inheritance.cpp +9 -9
  67. data/test/test_Iterator.cpp +134 -5
  68. data/test/test_Keep_Alive.cpp +7 -7
  69. data/test/test_Memory_Management.cpp +1 -1
  70. data/test/test_Module.cpp +25 -62
  71. data/test/test_Object.cpp +66 -3
  72. data/test/test_Ownership.cpp +12 -13
  73. data/test/test_Self.cpp +12 -13
  74. data/test/test_Stl_Map.cpp +696 -0
  75. data/test/test_Stl_Optional.cpp +3 -3
  76. data/test/test_Stl_Pair.cpp +38 -2
  77. data/test/test_Stl_Reference_Wrapper.cpp +102 -0
  78. data/test/test_Stl_SmartPointer.cpp +5 -5
  79. data/test/test_Stl_Unordered_Map.cpp +697 -0
  80. data/test/test_Stl_Variant.cpp +301 -0
  81. data/test/test_Stl_Vector.cpp +200 -41
  82. data/test/test_Struct.cpp +3 -3
  83. data/test/test_To_From_Ruby.cpp +6 -0
  84. data/test/test_Tracking.cpp +239 -0
  85. data/test/unittest.hpp +13 -4
  86. metadata +23 -13
  87. data/rice/detail/Exception_Handler.hpp +0 -8
  88. data/rice/detail/Exception_Handler.ipp +0 -28
  89. data/rice/detail/Iterator.hpp +0 -23
  90. data/rice/detail/Iterator.ipp +0 -47
  91. data/rice/detail/function_traits.hpp +0 -124
  92. data/rice/detail/method_data.hpp +0 -29
  93. data/rice/detail/rice_traits.hpp +0 -116
  94. data/rice/ruby_try_catch.hpp +0 -86
data/lib/mkmf-rice.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'mkmf'
2
2
 
3
3
  IS_MSWIN = !RbConfig::CONFIG['host_os'].match(/mswin/).nil?
4
+ IS_MINGW = !RbConfig::CONFIG['host_os'].match(/mingw/).nil?
4
5
  IS_DARWIN = !RbConfig::CONFIG['host_os'].match(/darwin/).nil?
5
6
 
6
7
  # If we are on versions of Ruby before 2.7 then we need to copy in the experimental C++ support
@@ -106,8 +107,10 @@ include MakeMakefile['C++']
106
107
 
107
108
  # Rice needs c++17.
108
109
  if IS_MSWIN
109
- $CXXFLAGS += " /std:c++17 /EHsc /permissive-"
110
- $CPPFLAGS += " -D_ALLOW_KEYWORD_MACROS"
110
+ $CXXFLAGS += " /std:c++17 /EHsc /permissive- /bigobj"
111
+ $CPPFLAGS += " -D_ALLOW_KEYWORD_MACROS -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE"
112
+ elsif IS_MINGW
113
+ $CXXFLAGS += " -std=c++17 -Wa,-mbig-obj"
111
114
  else
112
115
  $CXXFLAGS += " -std=c++17"
113
116
  end
data/lib/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Rice
2
- VERSION = "4.0.4"
2
+ VERSION = "4.1.0"
3
3
  end
data/rice/Arg.hpp CHANGED
@@ -57,18 +57,17 @@ namespace Rice
57
57
  //! Tell the receiving object to keep this argument alive
58
58
  //! until the receiving object is freed.
59
59
  Arg& keepAlive();
60
+
61
+ //! Returns if the argument should be kept alive
62
+ bool isKeepAlive() const;
60
63
 
61
64
  //! Specifies if the argument should be treated as a value
62
- Arg& isValue();
65
+ Arg& setValue();
63
66
 
64
67
  //! Returns if the argument should be treated as a value
65
- bool getIsValue();
66
-
67
- // No longer supported - implemented to raise error
68
- Arg operator,(const Arg& other);
68
+ bool isValue() const;
69
69
 
70
70
  public:
71
- bool isKeepAlive = false;
72
71
  const std::string name;
73
72
  int32_t position = -1;
74
73
 
@@ -76,6 +75,7 @@ namespace Rice
76
75
  //! Our saved default value
77
76
  std::any defaultValue_;
78
77
  bool isValue_ = false;
78
+ bool isKeepAlive_ = false;
79
79
  };
80
80
  } // Rice
81
81
 
data/rice/Arg.ipp CHANGED
@@ -28,24 +28,23 @@ namespace Rice
28
28
 
29
29
  inline Arg& Arg::keepAlive()
30
30
  {
31
- this->isKeepAlive = true;
31
+ this->isKeepAlive_ = true;
32
32
  return *this;
33
33
  }
34
34
 
35
- inline Arg& Arg::isValue()
35
+ inline bool Arg::isKeepAlive() const
36
36
  {
37
- isValue_ = true;
38
- return *this;
37
+ return this->isKeepAlive_;
39
38
  }
40
39
 
41
- inline bool Arg::getIsValue()
40
+ inline Arg& Arg::setValue()
42
41
  {
43
- return isValue_;
42
+ isValue_ = true;
43
+ return *this;
44
44
  }
45
45
 
46
- // Function to overload the, operator
47
- inline Arg Arg::operator,(const Arg& other)
46
+ inline bool Arg::isValue() const
48
47
  {
49
- throw std::runtime_error("The Arg class no longer supports the comma operator, please remove the surounding parentheses");
48
+ return isValue_;
50
49
  }
51
50
  } // Rice
data/rice/Constructor.hpp CHANGED
@@ -26,7 +26,7 @@ namespace Rice
26
26
  static void construct(VALUE self, Arg_Ts...args)
27
27
  {
28
28
  T* data = new T(args...);
29
- detail::replace<T>(self, Data_Type<T>::rb_type(), data, true);
29
+ detail::replace<T>(self, Data_Type<T>::ruby_data_type(), data, true);
30
30
  }
31
31
  };
32
32
 
@@ -38,7 +38,7 @@ namespace Rice
38
38
  static void construct(Object self, Arg_Ts...args)
39
39
  {
40
40
  T* data = new T(self, args...);
41
- detail::replace<T>(self.value(), Data_Type<T>::rb_type(), data, true);
41
+ detail::replace<T>(self.value(), Data_Type<T>::ruby_data_type(), data, true);
42
42
  }
43
43
  };
44
44
  }
data/rice/Data_Object.ipp CHANGED
@@ -18,27 +18,19 @@ namespace Rice
18
18
  template<typename T>
19
19
  inline Data_Object<T>::Data_Object(T& data, bool isOwner, Class klass)
20
20
  {
21
- VALUE value = detail::wrap(klass, Data_Type<T>::rb_type(), data, isOwner);
21
+ VALUE value = detail::wrap(klass, Data_Type<T>::ruby_data_type(), data, isOwner);
22
22
  this->set_value(value);
23
23
  }
24
24
 
25
25
  template<typename T>
26
26
  inline Data_Object<T>::Data_Object(T* data, bool isOwner, Class klass)
27
27
  {
28
- VALUE value = detail::wrap(klass, Data_Type<T>::rb_type(), data, isOwner);
28
+ VALUE value = detail::wrap(klass, Data_Type<T>::ruby_data_type(), data, isOwner);
29
29
  this->set_value(value);
30
30
  }
31
31
 
32
32
  template<typename T>
33
33
  inline Data_Object<T>::Data_Object(Object value) : Object(value)
34
- {
35
- Data_Type<T> klass;
36
- check_ruby_type(value);
37
- }
38
-
39
- template<typename T>
40
- template<typename U>
41
- inline Data_Object<T>::Data_Object(Object value) : Object(value)
42
34
  {
43
35
  check_ruby_type(value);
44
36
  }
@@ -73,7 +65,7 @@ namespace Rice
73
65
  }
74
66
  else
75
67
  {
76
- return detail::unwrap<T>(this->value(), Data_Type<T>::rb_type());
68
+ return detail::unwrap<T>(this->value(), Data_Type<T>::ruby_data_type());
77
69
  }
78
70
  }
79
71
 
@@ -82,7 +74,7 @@ namespace Rice
82
74
  {
83
75
  if (Data_Type<T>::is_descendant(value))
84
76
  {
85
- return detail::unwrap<T>(value, Data_Type<T>::rb_type());
77
+ return detail::unwrap<T>(value, Data_Type<T>::ruby_data_type());
86
78
  }
87
79
  else
88
80
  {
@@ -100,7 +92,17 @@ namespace Rice::detail
100
92
  VALUE convert(T& data)
101
93
  {
102
94
  // Get the ruby typeinfo
103
- std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::TypeRegistry::figureType<T>(data);
95
+ std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType<T>(data);
96
+
97
+ // We always take ownership of data passed by value (yes the parameter is T& but the template
98
+ // matched <typename T> thus we have to tell wrap to copy the reference we are sending to it
99
+ return detail::wrap(rubyTypeInfo.first, rubyTypeInfo.second, data, true);
100
+ }
101
+
102
+ VALUE convert(const T& data)
103
+ {
104
+ // Get the ruby typeinfo
105
+ std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType<T>(data);
104
106
 
105
107
  // We always take ownership of data passed by value (yes the parameter is T& but the template
106
108
  // matched <typename T> thus we have to tell wrap to copy the reference we are sending to it
@@ -122,7 +124,17 @@ namespace Rice::detail
122
124
  {
123
125
  // Note that T could be a pointer or reference to a base class while data is in fact a
124
126
  // child class. Lookup the correct type so we return an instance of the correct Ruby class
125
- std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::TypeRegistry::figureType<T>(data);
127
+ std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType<T>(data);
128
+
129
+ bool isOwner = this->returnInfo_ && this->returnInfo_->isOwner();
130
+ return detail::wrap(rubyTypeInfo.first, rubyTypeInfo.second, data, isOwner);
131
+ }
132
+
133
+ VALUE convert(const T& data)
134
+ {
135
+ // Note that T could be a pointer or reference to a base class while data is in fact a
136
+ // child class. Lookup the correct type so we return an instance of the correct Ruby class
137
+ std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType<T>(data);
126
138
 
127
139
  bool isOwner = this->returnInfo_ && this->returnInfo_->isOwner();
128
140
  return detail::wrap(rubyTypeInfo.first, rubyTypeInfo.second, data, isOwner);
@@ -142,13 +154,29 @@ namespace Rice::detail
142
154
  {
143
155
  }
144
156
 
157
+ VALUE convert(T* data)
158
+ {
159
+ if (data)
160
+ {
161
+ // Note that T could be a pointer or reference to a base class while data is in fact a
162
+ // child class. Lookup the correct type so we return an instance of the correct Ruby class
163
+ std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType(*data);
164
+ bool isOwner = this->returnInfo_ && this->returnInfo_->isOwner();
165
+ return detail::wrap(rubyTypeInfo.first, rubyTypeInfo.second, data, isOwner);
166
+ }
167
+ else
168
+ {
169
+ return Qnil;
170
+ }
171
+ }
172
+
145
173
  VALUE convert(const T* data)
146
174
  {
147
175
  if (data)
148
176
  {
149
177
  // Note that T could be a pointer or reference to a base class while data is in fact a
150
178
  // child class. Lookup the correct type so we return an instance of the correct Ruby class
151
- std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::TypeRegistry::figureType(*data);
179
+ std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType(*data);
152
180
  bool isOwner = this->returnInfo_ && this->returnInfo_->isOwner();
153
181
  return detail::wrap(rubyTypeInfo.first, rubyTypeInfo.second, data, isOwner);
154
182
  }
@@ -175,6 +203,8 @@ namespace Rice::detail
175
203
  template <typename T>
176
204
  class From_Ruby
177
205
  {
206
+ static_assert(!std::is_fundamental_v<intrinsic_type<T>>,
207
+ "Data_Object cannot be used with fundamental types");
178
208
  public:
179
209
  From_Ruby() = default;
180
210
 
@@ -182,6 +212,12 @@ namespace Rice::detail
182
212
  {
183
213
  }
184
214
 
215
+ bool is_convertible(VALUE value)
216
+ {
217
+ return rb_type(value) == RUBY_T_DATA &&
218
+ Data_Type<T>::is_descendant(value);
219
+ }
220
+
185
221
  T convert(VALUE value)
186
222
  {
187
223
  using Intrinsic_T = intrinsic_type<T>;
@@ -203,6 +239,8 @@ namespace Rice::detail
203
239
  template<typename T>
204
240
  class From_Ruby<T&>
205
241
  {
242
+ static_assert(!std::is_fundamental_v<intrinsic_type<T>>,
243
+ "Data_Object cannot be used with fundamental types");
206
244
  public:
207
245
  From_Ruby() = default;
208
246
 
@@ -210,6 +248,12 @@ namespace Rice::detail
210
248
  {
211
249
  }
212
250
 
251
+ bool is_convertible(VALUE value)
252
+ {
253
+ return rb_type(value) == RUBY_T_DATA &&
254
+ Data_Type<T>::is_descendant(value);
255
+ }
256
+
213
257
  T& convert(VALUE value)
214
258
  {
215
259
  using Intrinsic_T = intrinsic_type<T>;
@@ -231,7 +275,15 @@ namespace Rice::detail
231
275
  template<typename T>
232
276
  class From_Ruby<T*>
233
277
  {
278
+ static_assert(!std::is_fundamental_v<intrinsic_type<T>>,
279
+ "Data_Object cannot be used with fundamental types");
234
280
  public:
281
+ bool is_convertible(VALUE value)
282
+ {
283
+ return rb_type(value) == RUBY_T_DATA &&
284
+ Data_Type<T>::is_descendant(value);
285
+ }
286
+
235
287
  T* convert(VALUE value)
236
288
  {
237
289
  using Intrinsic_T = intrinsic_type<T>;
@@ -250,6 +302,8 @@ namespace Rice::detail
250
302
  template<typename T>
251
303
  class From_Ruby<Data_Object<T>>
252
304
  {
305
+ static_assert(!std::is_fundamental_v<intrinsic_type<T>>,
306
+ "Data_Object cannot be used with fundamental types");
253
307
  public:
254
308
  static Data_Object<T> convert(VALUE value)
255
309
  {
@@ -48,7 +48,6 @@ namespace Rice
48
48
 
49
49
  public:
50
50
  static T* from_ruby(VALUE value);
51
- static std::optional<T> implicit_from_ruby(VALUE value);
52
51
 
53
52
  public:
54
53
  //! Wrap a C++ object.
@@ -58,12 +57,9 @@ namespace Rice
58
57
  * constructed objects that need to be managed by Ruby's garbage
59
58
  * collector).
60
59
  * \param obj the object to wrap.
60
+ * \param isOwner Should the Data_Object take ownership of the object?
61
61
  * \param klass the Ruby class to use for the newly created Ruby
62
62
  * object.
63
- * \param mark_func a function that gets called by the garbage
64
- * collector to mark the object's children.
65
- * \param free_func a function that gets called by the garbage
66
- * collector to free the object.
67
63
  */
68
64
  Data_Object(T* obj, bool isOwner = false, Class klass = Data_Type<T>::klass());
69
65
  Data_Object(T& obj, bool isOwner = false, Class klass = Data_Type<T>::klass());
@@ -75,16 +71,6 @@ namespace Rice
75
71
  */
76
72
  Data_Object(Object value);
77
73
 
78
- //! Unwrap a Ruby object.
79
- /*! This constructor is analogous to calling Data_Get_Struct. Will
80
- * throw an exception if the class of the object differs from the
81
- * specified class.
82
- * \param value the Ruby object to unwrap.
83
- * \param klass the expected class of the object.
84
- */
85
- template<typename U>
86
- Data_Object(Object value);
87
-
88
74
  T& operator*() const; //!< Return a reference to obj_
89
75
  T* operator->() const; //!< Return a pointer to obj_
90
76
  T* get() const; //!< Return a pointer to obj_
data/rice/Data_Type.ipp CHANGED
@@ -1,14 +1,16 @@
1
1
  #ifndef Rice__Data_Type__ipp_
2
2
  #define Rice__Data_Type__ipp_
3
3
 
4
- #include "detail/method_data.hpp"
4
+ #include "traits/attribute_traits.hpp"
5
+ #include "traits/method_traits.hpp"
6
+ #include "detail/NativeRegistry.hpp"
5
7
  #include "detail/NativeAttribute.hpp"
6
8
  #include "detail/default_allocation_func.hpp"
7
9
  #include "detail/TypeRegistry.hpp"
8
10
  #include "detail/Wrapper.hpp"
9
- #include "detail/Iterator.hpp"
10
- #include "Class.hpp"
11
- #include "String.hpp"
11
+ #include "detail/NativeIterator.hpp"
12
+ #include "cpp_api/Class.hpp"
13
+ #include "cpp_api/String.hpp"
12
14
 
13
15
  #include <stdexcept>
14
16
 
@@ -39,7 +41,7 @@ namespace Rice
39
41
 
40
42
  template<typename T>
41
43
  template <typename Base_T>
42
- inline Data_Type<T> Data_Type<T>::bind(Module const& klass)
44
+ inline Data_Type<T> Data_Type<T>::bind(const Module& klass)
43
45
  {
44
46
  if (is_bound())
45
47
  {
@@ -49,21 +51,21 @@ namespace Rice
49
51
 
50
52
  klass_ = klass;
51
53
 
52
- rb_type_ = new rb_data_type_t();
53
- rb_type_->wrap_struct_name = strdup(Rice::detail::protect(rb_class2name, klass_));
54
- rb_type_->function.dmark = reinterpret_cast<void(*)(void*)>(&Rice::ruby_mark_internal<T>);
55
- rb_type_->function.dfree = reinterpret_cast<void(*)(void*)>(&Rice::ruby_free_internal<T>);
56
- rb_type_->function.dsize = reinterpret_cast<size_t(*)(const void*)>(&Rice::ruby_size_internal<T>);
57
- rb_type_->data = nullptr;
58
- rb_type_->flags = RUBY_TYPED_FREE_IMMEDIATELY;
54
+ rb_data_type_ = new rb_data_type_t();
55
+ rb_data_type_->wrap_struct_name = strdup(Rice::detail::protect(rb_class2name, klass_));
56
+ rb_data_type_->function.dmark = reinterpret_cast<void(*)(void*)>(&Rice::ruby_mark_internal<T>);
57
+ rb_data_type_->function.dfree = reinterpret_cast<void(*)(void*)>(&Rice::ruby_free_internal<T>);
58
+ rb_data_type_->function.dsize = reinterpret_cast<size_t(*)(const void*)>(&Rice::ruby_size_internal<T>);
59
+ rb_data_type_->data = nullptr;
60
+ rb_data_type_->flags = RUBY_TYPED_FREE_IMMEDIATELY;
59
61
 
60
62
  if constexpr (!std::is_void_v<Base_T>)
61
63
  {
62
- rb_type_->parent = Data_Type<Base_T>::rb_type();
64
+ rb_data_type_->parent = Data_Type<Base_T>::ruby_data_type();
63
65
  }
64
66
 
65
67
  // Now register with the type registry
66
- detail::TypeRegistry::add<T>(klass_, rb_type_);
68
+ detail::Registries::instance.types.add<T>(klass_, rb_data_type_);
67
69
 
68
70
  for (typename Instances::iterator it = unbound_instances().begin(),
69
71
  end = unbound_instances().end();
@@ -79,7 +81,7 @@ namespace Rice
79
81
  template<typename T>
80
82
  inline void Data_Type<T>::unbind()
81
83
  {
82
- detail::TypeRegistry::remove<T>();
84
+ detail::Registries::instance.types.remove<T>();
83
85
 
84
86
  if (klass_ != Qnil)
85
87
  {
@@ -88,7 +90,7 @@ namespace Rice
88
90
 
89
91
  // There could be objects floating around using the existing rb_type so
90
92
  // do not delete it. This is of course a memory leak.
91
- rb_type_ = nullptr;
93
+ rb_data_type_ = nullptr;
92
94
  }
93
95
 
94
96
  template<typename T>
@@ -113,10 +115,10 @@ namespace Rice
113
115
  }
114
116
 
115
117
  template<typename T>
116
- inline rb_data_type_t* Data_Type<T>::rb_type()
118
+ inline rb_data_type_t* Data_Type<T>::ruby_data_type()
117
119
  {
118
120
  check_is_bound();
119
- return rb_type_;
121
+ return rb_data_type_;
120
122
  }
121
123
 
122
124
  template<typename T>
@@ -133,19 +135,6 @@ namespace Rice
133
135
  return *this;
134
136
  }
135
137
 
136
- template<typename T>
137
- template<typename Constructor_T>
138
- inline Data_Type<T>& Data_Type<T>::define_constructor(Constructor_T, MethodInfo* methodInfo)
139
- {
140
- check_is_bound();
141
-
142
- // Normal constructor pattern with new/initialize
143
- detail::protect(rb_define_alloc_func, static_cast<VALUE>(*this), detail::default_allocation_func<T>);
144
- this->define_method("initialize", &Constructor_T::construct, methodInfo);
145
-
146
- return *this;
147
- }
148
-
149
138
  template<typename T>
150
139
  template<typename Constructor_T, typename...Arg_Ts>
151
140
  inline Data_Type<T>& Data_Type<T>::define_constructor(Constructor_T constructor, Arg_Ts const& ...args)
@@ -165,14 +154,14 @@ namespace Rice
165
154
  template<typename Director_T>
166
155
  inline Data_Type<T>& Data_Type<T>::define_director()
167
156
  {
168
- if (!detail::TypeRegistry::isDefined<Director_T>())
157
+ if (!detail::Registries::instance.types.isDefined<Director_T>())
169
158
  {
170
159
  Data_Type<Director_T>::bind(*this);
171
160
  }
172
161
 
173
162
  // TODO - hack to fake Ruby into thinking that a Director is
174
163
  // the same as the base data type
175
- Data_Type<Director_T>::rb_type_ = Data_Type<T>::rb_type_;
164
+ Data_Type<Director_T>::rb_data_type_ = Data_Type<T>::rb_data_type_;
176
165
  return *this;
177
166
  }
178
167
 
@@ -202,7 +191,7 @@ namespace Rice
202
191
  template<typename T, typename Base_T>
203
192
  inline Data_Type<T> define_class_under(Object module, char const* name)
204
193
  {
205
- if (detail::TypeRegistry::isDefined<T>())
194
+ if (detail::Registries::instance.types.isDefined<T>())
206
195
  {
207
196
  return Data_Type<T>();
208
197
  }
@@ -226,7 +215,7 @@ namespace Rice
226
215
  template<typename T, typename Base_T>
227
216
  inline Data_Type<T> define_class(char const* name)
228
217
  {
229
- if (detail::TypeRegistry::isDefined<T>())
218
+ if (detail::Registries::instance.types.isDefined<T>())
230
219
  {
231
220
  return Data_Type<T>();
232
221
  }
@@ -247,75 +236,56 @@ namespace Rice
247
236
  }
248
237
 
249
238
  template<typename T>
250
- template<typename U, typename Iterator_T>
251
- inline Data_Type<T>& Data_Type<T>::define_iterator(Iterator_T(U::* begin)(), Iterator_T(U::* end)(), Identifier name)
239
+ template<typename Iterator_Func_T>
240
+ inline Data_Type<T>& Data_Type<T>::define_iterator(Iterator_Func_T begin, Iterator_Func_T end, std::string name)
252
241
  {
253
- using Iter_T = detail::Iterator<U, Iterator_T>;
254
- Iter_T* iterator = new Iter_T(begin, end);
255
- detail::MethodData::define_method(Data_Type<T>::klass(), name,
256
- (RUBY_METHOD_FUNC)iterator->call, 0, iterator);
242
+ // Define a NativeIterator to bridge Ruby to C++
243
+ detail::NativeIterator<T, Iterator_Func_T>::define(Data_Type<T>::klass(), name, begin, end);
244
+
245
+ // Include enumerable support
246
+ this->klass().include_module(rb_mEnumerable);
257
247
 
258
248
  return *this;
259
249
  }
260
250
 
261
251
  template <typename T>
262
- template <typename Attr_T>
263
- inline Data_Type<T>& Data_Type<T>::define_attr(std::string name, Attr_T attr, AttrAccess access)
252
+ template <typename Attribute_T>
253
+ inline Data_Type<T>& Data_Type<T>::define_attr(std::string name, Attribute_T attribute, AttrAccess access)
264
254
  {
265
- auto* native = detail::Make_Native_Attribute(attr, access);
266
- using Native_T = typename std::remove_pointer_t<decltype(native)>;
267
-
268
- detail::verifyType<typename Native_T::Native_Return_T>();
269
-
270
- if (access == AttrAccess::ReadWrite || access == AttrAccess::Read)
271
- {
272
- detail::MethodData::define_method( klass_, Identifier(name).id(),
273
- RUBY_METHOD_FUNC(&Native_T::get), 0, native);
274
- }
275
-
276
- if (access == AttrAccess::ReadWrite || access == AttrAccess::Write)
277
- {
278
- if (std::is_const_v<std::remove_pointer_t<Attr_T>>)
279
- {
280
- throw std::runtime_error(name + " is readonly");
281
- }
255
+ // Make sure the Attribute type has been previously seen by Rice
256
+ detail::verifyType<typename detail::attribute_traits<Attribute_T>::attr_type>();
282
257
 
283
- detail::MethodData::define_method( klass_, Identifier(name + "=").id(),
284
- RUBY_METHOD_FUNC(&Native_T::set), 1, native);
285
- }
258
+ // Define native attribute
259
+ detail::NativeAttribute<Attribute_T>::define(klass_, name, std::forward<Attribute_T>(attribute), access);
286
260
 
287
261
  return *this;
288
262
  }
289
263
 
290
264
  template <typename T>
291
- template <typename Attr_T>
292
- inline Data_Type<T>& Data_Type<T>::define_singleton_attr(std::string name, Attr_T attr, AttrAccess access)
265
+ template <typename Attribute_T>
266
+ inline Data_Type<T>& Data_Type<T>::define_singleton_attr(std::string name, Attribute_T attribute, AttrAccess access)
293
267
  {
294
- auto* native = detail::Make_Native_Attribute(attr, access);
295
- using Native_T = typename std::remove_pointer_t<decltype(native)>;
268
+ // Make sure the Attribute type has been previously seen by Rice
269
+ detail::verifyType<typename detail::attribute_traits<Attribute_T>::attr_type>();
296
270
 
297
- detail::verifyType<typename Native_T::Native_Return_T>();
271
+ // Define native attribute
272
+ VALUE singleton = detail::protect(rb_singleton_class, this->value());
273
+ detail::NativeAttribute<Attribute_T>::define(singleton, name, std::forward<Attribute_T>(attribute), access);
298
274
 
299
- if (access == AttrAccess::ReadWrite || access == AttrAccess::Read)
300
- {
301
- VALUE singleton = detail::protect(rb_singleton_class, this->value());
302
- detail::MethodData::define_method(singleton, Identifier(name).id(),
303
- RUBY_METHOD_FUNC(&Native_T::get), 0, native);
304
- }
275
+ return *this;
276
+ }
305
277
 
306
- if (access == AttrAccess::ReadWrite || access == AttrAccess::Write)
307
- {
308
- if (std::is_const_v<std::remove_pointer_t<Attr_T>>)
309
- {
310
- throw std::runtime_error(name + " is readonly");
311
- }
312
-
313
- VALUE singleton = detail::protect(rb_singleton_class, this->value());
314
- detail::MethodData::define_method(singleton, Identifier(name + "=").id(),
315
- RUBY_METHOD_FUNC(&Native_T::set), 1, native);
316
- }
278
+ template <typename T>
279
+ template<bool IsMethod, typename Function_T>
280
+ inline void Data_Type<T>::wrap_native_call(VALUE klass, std::string name, Function_T&& function, MethodInfo* methodInfo)
281
+ {
282
+ // Make sure the return type and arguments have been previously seen by Rice
283
+ using traits = detail::method_traits<Function_T, IsMethod>;
284
+ detail::verifyType<typename traits::Return_T>();
285
+ detail::verifyTypes<typename traits::Arg_Ts>();
317
286
 
318
- return *this;
287
+ // Define a NativeFunction to bridge Ruby to C++
288
+ detail::NativeFunction<T, Function_T, IsMethod>::define(klass, name, std::forward<Function_T>(function), methodInfo);
319
289
  }
320
290
  }
321
291
  #endif
@@ -1,7 +1,7 @@
1
1
  #ifndef Rice__Data_Type_defn__hpp_
2
2
  #define Rice__Data_Type_defn__hpp_
3
3
 
4
- #include "Class_defn.hpp"
4
+ #include "cpp_api/Class_defn.hpp"
5
5
  #include "detail/ruby.hpp"
6
6
  #include <set>
7
7
 
@@ -38,8 +38,8 @@ namespace Rice
38
38
  */
39
39
  static Class klass();
40
40
 
41
- //! Return the Ruby type.
42
- static rb_data_type_t* rb_type();
41
+ //! Return the Ruby data type.
42
+ static rb_data_type_t* ruby_data_type();
43
43
 
44
44
  //! Assignment operator which takes a Module
45
45
  /*! \param klass must be the class to which this data type is already
@@ -48,11 +48,6 @@ namespace Rice
48
48
  */
49
49
  virtual Data_Type & operator=(Module const & klass);
50
50
 
51
- //! Define a constructor for the class.
52
- template<typename Constructor_T>
53
- [[deprecated("Please call define_constructor with Arg parameters")]]
54
- Data_Type<T> & define_constructor(Constructor_T constructor, MethodInfo * methodInfo);
55
-
56
51
  /*! Creates a singleton method allocate and an instance method called
57
52
  * initialize which together create a new instance of the class. The
58
53
  * allocate method allocates memory for the object reference and the
@@ -118,14 +113,14 @@ namespace Rice
118
113
  * \return *this
119
114
  */
120
115
 
121
- template<typename U = T, typename Iterator_Return_T>
122
- Data_Type<T>& define_iterator(Iterator_Return_T(U::* begin)(), Iterator_Return_T(U::* end)(), Identifier name = "each");
116
+ template<typename Iterator_Func_T>
117
+ Data_Type<T>& define_iterator(Iterator_Func_T begin, Iterator_Func_T end, std::string name = "each");
123
118
 
124
- template <typename Attr_T>
125
- Data_Type<T>& define_attr(std::string name, Attr_T attr, AttrAccess access = AttrAccess::ReadWrite);
119
+ template <typename Attribute_T>
120
+ Data_Type<T>& define_attr(std::string name, Attribute_T attribute, AttrAccess access = AttrAccess::ReadWrite);
126
121
 
127
- template <typename Attr_T>
128
- Data_Type<T>& define_singleton_attr(std::string name, Attr_T attr, AttrAccess access = AttrAccess::ReadWrite);
122
+ template <typename Attribute_T>
123
+ Data_Type<T>& define_singleton_attr(std::string name, Attribute_T attribute, AttrAccess access = AttrAccess::ReadWrite);
129
124
 
130
125
  #include "cpp_api/shared_methods.hpp"
131
126
 
@@ -138,7 +133,7 @@ namespace Rice
138
133
  * \return *this
139
134
  */
140
135
  template <typename Base_T = void>
141
- static Data_Type bind(Module const & klass);
136
+ static Data_Type bind(const Module& klass);
142
137
 
143
138
  template<typename T_, typename Base_T_>
144
139
  friend Rice::Data_Type<T_> define_class_under(Object module, char const * name);
@@ -146,6 +141,9 @@ namespace Rice
146
141
  template<typename T_, typename Base_T_>
147
142
  friend Rice::Data_Type<T_> define_class(char const * name);
148
143
 
144
+ template<bool IsMethod, typename Function_T>
145
+ void wrap_native_call(VALUE klass, std::string name, Function_T&& function, MethodInfo* methodInfo);
146
+
149
147
  private:
150
148
  template<typename T_>
151
149
  friend class Data_Type;
@@ -153,7 +151,7 @@ namespace Rice
153
151
  static inline VALUE klass_ = Qnil;
154
152
 
155
153
  // Typed Data support
156
- static inline rb_data_type_t* rb_type_ = nullptr;
154
+ static inline rb_data_type_t* rb_data_type_ = nullptr;
157
155
 
158
156
  typedef std::set<Data_Type<T> *> Instances;
159
157
 
@@ -185,7 +183,6 @@ namespace Rice
185
183
  */
186
184
  template<typename T, typename Base_T = void>
187
185
  Data_Type<T> define_class(char const* name);
188
-
189
186
  } // namespace Rice
190
187
 
191
188
  #include "Data_Type.ipp"