rice 4.0.4 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
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"