rice 2.1.2 → 4.0.1

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 (245) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +121 -0
  3. data/CONTRIBUTORS.md +19 -0
  4. data/COPYING +2 -2
  5. data/Gemfile +3 -0
  6. data/README.md +45 -1028
  7. data/Rakefile +95 -12
  8. data/include/rice/rice.hpp +7766 -0
  9. data/lib/mkmf-rice.rb +127 -0
  10. data/lib/version.rb +3 -0
  11. data/rice/Address_Registration_Guard.ipp +75 -32
  12. data/rice/Address_Registration_Guard_defn.hpp +60 -56
  13. data/rice/Arg.hpp +80 -4
  14. data/rice/Arg.ipp +51 -0
  15. data/rice/Constructor.hpp +30 -376
  16. data/rice/Data_Object.ipp +234 -107
  17. data/rice/Data_Object_defn.hpp +77 -117
  18. data/rice/Data_Type.hpp +1 -2
  19. data/rice/Data_Type.ipp +251 -295
  20. data/rice/Data_Type_defn.hpp +175 -243
  21. data/rice/Director.hpp +14 -9
  22. data/rice/Enum.hpp +54 -104
  23. data/rice/Enum.ipp +104 -230
  24. data/rice/Exception.hpp +2 -8
  25. data/rice/Exception.ipp +65 -0
  26. data/rice/Exception_defn.hpp +46 -47
  27. data/rice/Identifier.hpp +28 -28
  28. data/rice/Identifier.ipp +23 -27
  29. data/rice/Return.hpp +39 -0
  30. data/rice/Return.ipp +33 -0
  31. data/rice/detail/Exception_Handler.ipp +22 -62
  32. data/rice/detail/Exception_Handler_defn.hpp +76 -91
  33. data/rice/detail/Iterator.hpp +18 -88
  34. data/rice/detail/Iterator.ipp +47 -0
  35. data/rice/detail/Jump_Tag.hpp +21 -0
  36. data/rice/detail/MethodInfo.hpp +44 -0
  37. data/rice/detail/MethodInfo.ipp +78 -0
  38. data/rice/detail/NativeAttribute.hpp +53 -0
  39. data/rice/detail/NativeAttribute.ipp +83 -0
  40. data/rice/detail/NativeFunction.hpp +69 -0
  41. data/rice/detail/NativeFunction.ipp +248 -0
  42. data/rice/detail/RubyFunction.hpp +39 -0
  43. data/rice/detail/RubyFunction.ipp +92 -0
  44. data/rice/detail/Type.hpp +29 -0
  45. data/rice/detail/Type.ipp +138 -0
  46. data/rice/detail/TypeRegistry.hpp +50 -0
  47. data/rice/detail/TypeRegistry.ipp +106 -0
  48. data/rice/detail/Wrapper.hpp +51 -0
  49. data/rice/detail/Wrapper.ipp +151 -0
  50. data/rice/detail/default_allocation_func.hpp +8 -19
  51. data/rice/detail/default_allocation_func.ipp +9 -8
  52. data/rice/detail/from_ruby.hpp +2 -37
  53. data/rice/detail/from_ruby.ipp +1020 -46
  54. data/rice/detail/from_ruby_defn.hpp +38 -0
  55. data/rice/detail/function_traits.hpp +124 -0
  56. data/rice/detail/method_data.hpp +23 -15
  57. data/rice/detail/method_data.ipp +53 -0
  58. data/rice/detail/rice_traits.hpp +116 -0
  59. data/rice/detail/ruby.hpp +9 -49
  60. data/rice/detail/to_ruby.hpp +3 -17
  61. data/rice/detail/to_ruby.ipp +409 -31
  62. data/rice/detail/to_ruby_defn.hpp +48 -0
  63. data/rice/forward_declares.ipp +82 -0
  64. data/rice/global_function.hpp +16 -20
  65. data/rice/global_function.ipp +8 -17
  66. data/rice/rice.hpp +59 -0
  67. data/rice/ruby_mark.hpp +5 -3
  68. data/rice/ruby_try_catch.hpp +4 -4
  69. data/rice/stl.hpp +11 -0
  70. data/sample/callbacks/extconf.rb +6 -0
  71. data/sample/callbacks/sample_callbacks.cpp +35 -0
  72. data/sample/callbacks/test.rb +28 -0
  73. data/sample/enum/extconf.rb +3 -0
  74. data/sample/enum/sample_enum.cpp +3 -17
  75. data/sample/enum/test.rb +2 -2
  76. data/sample/inheritance/animals.cpp +8 -24
  77. data/sample/inheritance/extconf.rb +3 -0
  78. data/sample/inheritance/test.rb +1 -1
  79. data/sample/map/extconf.rb +3 -0
  80. data/sample/map/map.cpp +10 -18
  81. data/sample/map/test.rb +1 -1
  82. data/test/embed_ruby.cpp +34 -0
  83. data/test/embed_ruby.hpp +4 -0
  84. data/test/ext/t1/extconf.rb +3 -0
  85. data/test/ext/t1/t1.cpp +1 -3
  86. data/test/ext/t2/extconf.rb +3 -0
  87. data/test/ext/t2/t2.cpp +1 -1
  88. data/test/extconf.rb +23 -0
  89. data/test/ruby/test_callbacks_sample.rb +28 -0
  90. data/test/ruby/test_multiple_extensions.rb +18 -0
  91. data/test/ruby/test_multiple_extensions_same_class.rb +14 -0
  92. data/test/ruby/test_multiple_extensions_with_inheritance.rb +20 -0
  93. data/test/test_Address_Registration_Guard.cpp +25 -11
  94. data/test/test_Array.cpp +131 -74
  95. data/test/test_Attribute.cpp +147 -0
  96. data/test/test_Builtin_Object.cpp +36 -15
  97. data/test/test_Class.cpp +151 -276
  98. data/test/test_Constructor.cpp +10 -9
  99. data/test/test_Data_Object.cpp +135 -193
  100. data/test/test_Data_Type.cpp +323 -252
  101. data/test/test_Director.cpp +56 -42
  102. data/test/test_Enum.cpp +230 -104
  103. data/test/test_Exception.cpp +7 -7
  104. data/test/test_Hash.cpp +33 -31
  105. data/test/test_Identifier.cpp +6 -6
  106. data/test/test_Inheritance.cpp +221 -0
  107. data/test/test_Iterator.cpp +161 -0
  108. data/test/test_Jump_Tag.cpp +1 -1
  109. data/test/test_Keep_Alive.cpp +161 -0
  110. data/test/test_Memory_Management.cpp +4 -5
  111. data/test/test_Module.cpp +169 -111
  112. data/test/test_Object.cpp +51 -19
  113. data/test/test_Ownership.cpp +275 -0
  114. data/test/test_Self.cpp +205 -0
  115. data/test/test_Stl_Optional.cpp +90 -0
  116. data/test/test_Stl_Pair.cpp +144 -0
  117. data/test/test_Stl_SmartPointer.cpp +200 -0
  118. data/test/test_Stl_String.cpp +74 -0
  119. data/test/test_Stl_Vector.cpp +652 -0
  120. data/test/test_String.cpp +3 -3
  121. data/test/test_Struct.cpp +31 -40
  122. data/test/test_Symbol.cpp +3 -3
  123. data/test/test_To_From_Ruby.cpp +283 -218
  124. data/test/test_global_functions.cpp +41 -20
  125. data/test/unittest.cpp +34 -8
  126. data/test/unittest.hpp +0 -4
  127. metadata +120 -136
  128. data/Doxyfile +0 -2268
  129. data/Makefile.am +0 -26
  130. data/Makefile.in +0 -920
  131. data/README.mingw +0 -8
  132. data/aclocal.m4 +0 -1088
  133. data/bootstrap +0 -8
  134. data/check_stdcxx_11.ac +0 -142
  135. data/config.guess +0 -1421
  136. data/config.sub +0 -1807
  137. data/configure +0 -7481
  138. data/configure.ac +0 -55
  139. data/depcomp +0 -791
  140. data/doxygen.ac +0 -314
  141. data/doxygen.am +0 -186
  142. data/extconf.rb +0 -69
  143. data/install-sh +0 -501
  144. data/missing +0 -215
  145. data/post-autoconf.rb +0 -22
  146. data/post-automake.rb +0 -28
  147. data/rice/Address_Registration_Guard.cpp +0 -22
  148. data/rice/Arg_impl.hpp +0 -129
  149. data/rice/Arg_operators.cpp +0 -21
  150. data/rice/Arg_operators.hpp +0 -19
  151. data/rice/Array.hpp +0 -214
  152. data/rice/Array.ipp +0 -256
  153. data/rice/Builtin_Object.hpp +0 -8
  154. data/rice/Builtin_Object.ipp +0 -50
  155. data/rice/Builtin_Object_defn.hpp +0 -50
  156. data/rice/Class.cpp +0 -57
  157. data/rice/Class.hpp +0 -8
  158. data/rice/Class.ipp +0 -6
  159. data/rice/Class_defn.hpp +0 -83
  160. data/rice/Data_Type.cpp +0 -54
  161. data/rice/Data_Type_fwd.hpp +0 -12
  162. data/rice/Director.cpp +0 -13
  163. data/rice/Exception.cpp +0 -59
  164. data/rice/Exception_Base.hpp +0 -8
  165. data/rice/Exception_Base.ipp +0 -13
  166. data/rice/Exception_Base_defn.hpp +0 -27
  167. data/rice/Hash.hpp +0 -227
  168. data/rice/Hash.ipp +0 -329
  169. data/rice/Identifier.cpp +0 -8
  170. data/rice/Jump_Tag.hpp +0 -24
  171. data/rice/Makefile.am +0 -124
  172. data/rice/Makefile.in +0 -839
  173. data/rice/Module.cpp +0 -84
  174. data/rice/Module.hpp +0 -8
  175. data/rice/Module.ipp +0 -6
  176. data/rice/Module_defn.hpp +0 -88
  177. data/rice/Module_impl.hpp +0 -281
  178. data/rice/Module_impl.ipp +0 -345
  179. data/rice/Object.cpp +0 -169
  180. data/rice/Object.hpp +0 -8
  181. data/rice/Object.ipp +0 -19
  182. data/rice/Object_defn.hpp +0 -191
  183. data/rice/Require_Guard.hpp +0 -21
  184. data/rice/String.cpp +0 -94
  185. data/rice/String.hpp +0 -91
  186. data/rice/Struct.cpp +0 -117
  187. data/rice/Struct.hpp +0 -162
  188. data/rice/Struct.ipp +0 -26
  189. data/rice/Symbol.cpp +0 -25
  190. data/rice/Symbol.hpp +0 -66
  191. data/rice/Symbol.ipp +0 -44
  192. data/rice/config.hpp +0 -47
  193. data/rice/config.hpp.in +0 -46
  194. data/rice/detail/Arguments.hpp +0 -118
  195. data/rice/detail/Auto_Function_Wrapper.hpp +0 -898
  196. data/rice/detail/Auto_Function_Wrapper.ipp +0 -3694
  197. data/rice/detail/Auto_Member_Function_Wrapper.hpp +0 -897
  198. data/rice/detail/Auto_Member_Function_Wrapper.ipp +0 -2774
  199. data/rice/detail/Caster.hpp +0 -103
  200. data/rice/detail/Not_Copyable.hpp +0 -25
  201. data/rice/detail/Wrapped_Function.hpp +0 -33
  202. data/rice/detail/cfp.hpp +0 -24
  203. data/rice/detail/cfp.ipp +0 -51
  204. data/rice/detail/check_ruby_type.cpp +0 -27
  205. data/rice/detail/check_ruby_type.hpp +0 -23
  206. data/rice/detail/creation_funcs.hpp +0 -37
  207. data/rice/detail/creation_funcs.ipp +0 -36
  208. data/rice/detail/define_method_and_auto_wrap.hpp +0 -31
  209. data/rice/detail/define_method_and_auto_wrap.ipp +0 -30
  210. data/rice/detail/demangle.cpp +0 -56
  211. data/rice/detail/demangle.hpp +0 -19
  212. data/rice/detail/env.hpp +0 -11
  213. data/rice/detail/method_data.cpp +0 -86
  214. data/rice/detail/node.hpp +0 -13
  215. data/rice/detail/object_call.hpp +0 -69
  216. data/rice/detail/object_call.ipp +0 -131
  217. data/rice/detail/protect.cpp +0 -29
  218. data/rice/detail/protect.hpp +0 -34
  219. data/rice/detail/ruby_version_code.hpp +0 -6
  220. data/rice/detail/ruby_version_code.hpp.in +0 -6
  221. data/rice/detail/st.hpp +0 -22
  222. data/rice/detail/traits.hpp +0 -43
  223. data/rice/detail/win32.hpp +0 -16
  224. data/rice/detail/wrap_function.hpp +0 -341
  225. data/rice/detail/wrap_function.ipp +0 -514
  226. data/rice/protect.hpp +0 -92
  227. data/rice/protect.ipp +0 -1134
  228. data/rice/rubypp.rb +0 -97
  229. data/rice/to_from_ruby.hpp +0 -8
  230. data/rice/to_from_ruby.ipp +0 -294
  231. data/rice/to_from_ruby_defn.hpp +0 -70
  232. data/ruby.ac +0 -135
  233. data/ruby/Makefile.am +0 -1
  234. data/ruby/Makefile.in +0 -625
  235. data/ruby/lib/Makefile.am +0 -3
  236. data/ruby/lib/Makefile.in +0 -503
  237. data/ruby/lib/mkmf-rice.rb.in +0 -217
  238. data/ruby/lib/version.rb +0 -3
  239. data/sample/Makefile.am +0 -47
  240. data/sample/Makefile.in +0 -486
  241. data/test/Makefile.am +0 -72
  242. data/test/Makefile.in +0 -1150
  243. data/test/ext/Makefile.am +0 -41
  244. data/test/ext/Makefile.in +0 -480
  245. data/test/test_rice.rb +0 -41
data/rice/Data_Type.hpp CHANGED
@@ -4,5 +4,4 @@
4
4
  #include "Data_Type_defn.hpp"
5
5
  #include "Data_Type.ipp"
6
6
 
7
- #endif // Rice__Data_Type__hpp_
8
-
7
+ #endif // Rice__Data_Type__hpp_
data/rice/Data_Type.ipp CHANGED
@@ -1,365 +1,321 @@
1
1
  #ifndef Rice__Data_Type__ipp_
2
2
  #define Rice__Data_Type__ipp_
3
3
 
4
+ #include "detail/method_data.hpp"
5
+ #include "detail/NativeAttribute.hpp"
6
+ #include "detail/default_allocation_func.hpp"
7
+ #include "detail/TypeRegistry.hpp"
8
+ #include "detail/Wrapper.hpp"
9
+ #include "detail/Iterator.hpp"
4
10
  #include "Class.hpp"
5
11
  #include "String.hpp"
6
- #include "Data_Object.hpp"
7
- #include "detail/default_allocation_func.hpp"
8
- #include "detail/creation_funcs.hpp"
9
- #include "detail/method_data.hpp"
10
- #include "detail/Caster.hpp"
11
- #include "detail/demangle.hpp"
12
12
 
13
13
  #include <stdexcept>
14
- #include <typeinfo>
15
14
 
16
- template<typename T>
17
- VALUE Rice::Data_Type<T>::klass_ = Qnil;
15
+ namespace Rice
16
+ {
17
+ template<typename T>
18
+ void ruby_mark_internal(detail::Wrapper* wrapper)
19
+ {
20
+ // Tell the wrapper to mark the objects its keeping alive
21
+ wrapper->ruby_mark();
18
22
 
19
- template<typename T>
20
- std_unique_ptr<Rice::detail::Abstract_Caster> Rice::Data_Type<T>::caster_;
23
+ // Get the underlying data and call custom mark function (if any)
24
+ T* data = static_cast<T*>(wrapper->get());
25
+ ruby_mark<T>(data);
26
+ }
21
27
 
22
- template<typename T>
23
- template<typename Base_T>
24
- inline Rice::Data_Type<T> Rice::Data_Type<T>::
25
- bind(Module const & klass)
26
- {
27
- if(klass.value() == klass_)
28
+ template<typename T>
29
+ void ruby_free_internal(detail::Wrapper* wrapper)
28
30
  {
29
- return Data_Type<T>();
31
+ delete wrapper;
30
32
  }
31
33
 
32
- if(is_bound())
34
+ template<typename T>
35
+ size_t ruby_size_internal(const T* data)
33
36
  {
34
- std::string s;
35
- s = "Data type ";
36
- s += detail::demangle(typeid(T).name());
37
- s += " is already bound to a different type";
38
- throw std::runtime_error(s.c_str());
37
+ return sizeof(T);
39
38
  }
40
39
 
41
- // TODO: Make sure base type is bound; throw an exception otherwise.
42
- // We can't do this just yet, because we don't have a specialization
43
- // for binding to void.
44
- klass_ = klass;
40
+ template<typename T>
41
+ template <typename Base_T>
42
+ inline Data_Type<T> Data_Type<T>::bind(Module const& klass)
43
+ {
44
+ if (is_bound())
45
+ {
46
+ std::string message = "Type " + detail::typeName(typeid(T)) + " is already bound to a different type";
47
+ throw std::runtime_error(message.c_str());
48
+ }
49
+
50
+ klass_ = klass;
45
51
 
46
- // TODO: do we need to unregister when the program exits? we have to
47
- // be careful if we do, because the ruby interpreter might have
48
- // already shut down. The correct behavior is probably to register an
49
- // exit proc with the interpreter, so the proc gets called before the
50
- // GC shuts down.
51
- rb_gc_register_address(&klass_);
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;
52
59
 
53
- for(typename Instances::iterator it = unbound_instances().begin(),
60
+ if constexpr (!std::is_void_v<Base_T>)
61
+ {
62
+ rb_type_->parent = Data_Type<Base_T>::rb_type();
63
+ }
64
+
65
+ // Now register with the type registry
66
+ detail::TypeRegistry::add<T>(klass_, rb_type_);
67
+
68
+ for (typename Instances::iterator it = unbound_instances().begin(),
54
69
  end = unbound_instances().end();
55
70
  it != end;
56
71
  unbound_instances().erase(it++))
72
+ {
73
+ (*it)->set_value(klass);
74
+ }
75
+
76
+ return Data_Type<T>();
77
+ }
78
+
79
+ template<typename T>
80
+ inline void Data_Type<T>::unbind()
57
81
  {
58
- (*it)->set_value(klass);
82
+ detail::TypeRegistry::remove<T>();
83
+
84
+ if (klass_ != Qnil)
85
+ {
86
+ klass_ = Qnil;
87
+ }
88
+
89
+ // There could be objects floating around using the existing rb_type so
90
+ // do not delete it. This is of course a memory leak.
91
+ rb_type_ = nullptr;
59
92
  }
60
93
 
61
- detail::Abstract_Caster * base_caster = Data_Type<Base_T>().caster();
62
- caster_.reset(new detail::Caster<T, Base_T>(base_caster, klass));
63
- Data_Type_Base::casters().insert(std::make_pair(klass, caster_.get()));
64
- return Data_Type<T>();
65
- }
94
+ template<typename T>
95
+ inline Data_Type<T>::Data_Type() : Class(klass_ == Qnil ? rb_cObject : klass_)
96
+ {
97
+ if (!is_bound())
98
+ {
99
+ unbound_instances().insert(this);
100
+ }
101
+ }
66
102
 
67
- template<typename T>
68
- inline Rice::Data_Type<T>::
69
- Data_Type()
70
- : Module_impl<Data_Type_Base, Data_Type<T> >(
71
- klass_ == Qnil ? rb_cObject : klass_)
72
- {
73
- if(!is_bound())
103
+ template<typename T>
104
+ inline Data_Type<T>::Data_Type(Module const& klass) : Class(klass)
74
105
  {
75
- unbound_instances().insert(this);
106
+ this->bind(klass);
76
107
  }
77
- }
78
108
 
79
- template<typename T>
80
- inline Rice::Data_Type<T>::
81
- Data_Type(Module const & klass)
82
- : Module_impl<Data_Type_Base, Data_Type<T> >(
83
- klass)
84
- {
85
- this->bind<void>(klass);
86
- }
109
+ template<typename T>
110
+ inline Data_Type<T>::~Data_Type()
111
+ {
112
+ unbound_instances().erase(this);
113
+ }
87
114
 
88
- template<typename T>
89
- inline Rice::Data_Type<T>::
90
- ~Data_Type()
91
- {
92
- unbound_instances().erase(this);
93
- }
115
+ template<typename T>
116
+ inline rb_data_type_t* Data_Type<T>::rb_type()
117
+ {
118
+ check_is_bound();
119
+ return rb_type_;
120
+ }
94
121
 
95
- template<typename T>
96
- Rice::Module
97
- Rice::Data_Type<T>::
98
- klass() {
99
- if(is_bound())
122
+ template<typename T>
123
+ inline Class Data_Type<T>::klass()
100
124
  {
125
+ check_is_bound();
101
126
  return klass_;
102
127
  }
103
- else
128
+
129
+ template<typename T>
130
+ inline Data_Type<T>& Data_Type<T>::operator=(Module const& klass)
104
131
  {
105
- std::string s;
106
- s += detail::demangle(typeid(T *).name());
107
- s += " is unbound";
108
- throw std::runtime_error(s.c_str());
132
+ this->bind(klass);
133
+ return *this;
109
134
  }
110
- }
111
135
 
112
- template<typename T>
113
- Rice::Data_Type<T> & Rice::Data_Type<T>::
114
- operator=(Module const & klass)
115
- {
116
- this->bind<void>(klass);
117
- return *this;
118
- }
119
-
120
- template<typename T>
121
- template<typename Constructor_T>
122
- inline Rice::Data_Type<T> & Rice::Data_Type<T>::
123
- define_constructor(
124
- Constructor_T /* constructor */,
125
- Arguments* arguments)
126
- {
127
- check_is_bound();
128
-
129
- // Normal constructor pattern with new/initialize
130
- rb_define_alloc_func(
131
- static_cast<VALUE>(*this),
132
- detail::default_allocation_func<T>);
133
- this->define_method(
134
- "initialize",
135
- &Constructor_T::construct,
136
- arguments
137
- );
138
-
139
- return *this;
140
- }
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
141
 
142
- template<typename T>
143
- template<typename Constructor_T>
144
- inline Rice::Data_Type<T> & Rice::Data_Type<T>::
145
- define_constructor(
146
- Constructor_T constructor,
147
- Arg const& arg)
148
- {
149
- Arguments* args = new Arguments();
150
- args->add(arg);
151
- return define_constructor(constructor, args);
152
- }
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);
153
145
 
146
+ return *this;
147
+ }
154
148
 
155
- template<typename T>
156
- template<typename Director_T>
157
- inline Rice::Data_Type<T>& Rice::Data_Type<T>::
158
- define_director()
159
- {
160
- Rice::Data_Type<Director_T>::template bind<T>(*this);
161
- return *this;
162
- }
149
+ template<typename T>
150
+ template<typename Constructor_T, typename...Arg_Ts>
151
+ inline Data_Type<T>& Data_Type<T>::define_constructor(Constructor_T constructor, Arg_Ts const& ...args)
152
+ {
153
+ check_is_bound();
163
154
 
164
- template<typename T>
165
- inline T * Rice::Data_Type<T>::
166
- from_ruby(Object x)
167
- {
168
- check_is_bound();
155
+ // Define a Ruby allocator which creates the Ruby object
156
+ detail::protect(rb_define_alloc_func, static_cast<VALUE>(*this), detail::default_allocation_func<T>);
169
157
 
170
- void * v = DATA_PTR(x.value());
171
- Class klass = x.class_of();
158
+ // Define an initialize function that will create the C++ object
159
+ this->define_method("initialize", &Constructor_T::construct, args...);
172
160
 
173
- if(klass.value() == klass_)
174
- {
175
- // Great, not converting to a base/derived type
176
- Data_Type<T> data_klass;
177
- Data_Object<T> obj(x, data_klass);
178
- return obj.get();
161
+ return *this;
179
162
  }
180
163
 
181
- Data_Type_Base::Casters::const_iterator it = Data_Type_Base::casters().begin();
182
- Data_Type_Base::Casters::const_iterator end = Data_Type_Base::casters().end();
183
-
184
- // Finding the bound type that relates to the given klass is
185
- // a two step process. We iterate over the list of known type casters,
186
- // looking for:
187
- //
188
- // 1) casters that handle this direct type
189
- // 2) casters that handle types that are ancestors of klass
190
- //
191
- // Step 2 allows us to handle the case where a Rice-wrapped class
192
- // is subclassed in Ruby but then an instance of that class is passed
193
- // back into C++ (say, in a Listener / callback construction)
194
- //
195
-
196
- VALUE ancestors = rb_mod_ancestors(klass.value());
197
-
198
- long earliest = RARRAY_LEN(ancestors) + 1;
199
-
200
- int index;
201
- VALUE indexFound;
202
- Data_Type_Base::Casters::const_iterator toUse = end;
203
-
204
- for(; it != end; it++) {
205
- // Do we match directly?
206
- if(klass.value() == it->first) {
207
- toUse = it;
208
- break;
164
+ template<typename T>
165
+ template<typename Director_T>
166
+ inline Data_Type<T>& Data_Type<T>::define_director()
167
+ {
168
+ if (!detail::TypeRegistry::isDefined<Director_T>())
169
+ {
170
+ Data_Type<Director_T>::bind(*this);
209
171
  }
210
172
 
211
- // Check for ancestors. Trick is, we need to find the lowest
212
- // ancestor that does have a Caster to make sure that we're casting
213
- // to the closest C++ type that the Ruby class is subclassing.
214
- // There might be multiple ancestors that are also wrapped in
215
- // the extension, so find the earliest in the list and use that one.
216
- indexFound = rb_funcall(ancestors, rb_intern("index"), 1, it->first);
173
+ // TODO - hack to fake Ruby into thinking that a Director is
174
+ // the same as the base data type
175
+ Data_Type<Director_T>::rb_type_ = Data_Type<T>::rb_type_;
176
+ return *this;
177
+ }
217
178
 
218
- if(indexFound != Qnil) {
219
- index = NUM2INT(indexFound);
179
+ template<typename T>
180
+ inline bool Data_Type<T>::is_bound()
181
+ {
182
+ return klass_ != Qnil;
183
+ }
220
184
 
221
- if(index < earliest) {
222
- earliest = index;
223
- toUse = it;
224
- }
185
+ template<typename T>
186
+ inline bool Data_Type<T>::is_descendant(VALUE value)
187
+ {
188
+ check_is_bound();
189
+ return detail::protect(rb_obj_is_kind_of, value, klass_) == Qtrue;
190
+ }
191
+
192
+ template<typename T>
193
+ inline void Data_Type<T>::check_is_bound()
194
+ {
195
+ if (!is_bound())
196
+ {
197
+ std::string message = "Type " + detail::typeName(typeid(T)) + " is not bound";
198
+ throw std::runtime_error(message.c_str());
225
199
  }
226
200
  }
227
-
228
- if(toUse == end)
201
+
202
+ template<typename T, typename Base_T>
203
+ inline Data_Type<T> define_class_under(Object module, char const* name)
229
204
  {
230
- std::string s = "Class ";
231
- s += klass.name().str();
232
- s += " is not registered/bound in Rice";
233
- throw std::runtime_error(s);
205
+ if (detail::TypeRegistry::isDefined<T>())
206
+ {
207
+ return Data_Type<T>();
208
+ }
209
+
210
+ Class superKlass;
211
+
212
+ if constexpr (std::is_void_v<Base_T>)
213
+ {
214
+ superKlass = rb_cObject;
215
+ }
216
+ else
217
+ {
218
+ superKlass = Data_Type<Base_T>::klass();
219
+ }
220
+
221
+ Class c = define_class_under(module, name, superKlass);
222
+ c.undef_creation_funcs();
223
+ return Data_Type<T>::template bind<Base_T>(c);
234
224
  }
235
225
 
236
- detail::Abstract_Caster * caster = toUse->second;
237
- if(caster)
226
+ template<typename T, typename Base_T>
227
+ inline Data_Type<T> define_class(char const* name)
238
228
  {
239
- T * result = static_cast<T *>(caster->cast_to_base(v, klass_));
240
- return result;
229
+ if (detail::TypeRegistry::isDefined<T>())
230
+ {
231
+ return Data_Type<T>();
232
+ }
233
+
234
+ Class superKlass;
235
+ if constexpr (std::is_void_v<Base_T>)
236
+ {
237
+ superKlass = rb_cObject;
238
+ }
239
+ else
240
+ {
241
+ superKlass = Data_Type<Base_T>::klass();
242
+ }
243
+
244
+ Class c = define_class(name, superKlass);
245
+ c.undef_creation_funcs();
246
+ return Data_Type<T>::template bind<Base_T>(c);
241
247
  }
242
- else
248
+
249
+ 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)
243
252
  {
244
- return static_cast<T *>(v);
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);
257
+
258
+ return *this;
245
259
  }
246
- }
247
260
 
248
- template<typename T>
249
- inline bool Rice::Data_Type<T>::
250
- is_bound()
251
- {
252
- return klass_ != Qnil;
253
- }
261
+ 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)
264
+ {
265
+ auto* native = detail::Make_Native_Attribute(attr, access);
266
+ using Native_T = typename std::remove_pointer_t<decltype(native)>;
254
267
 
255
- template<typename T>
256
- inline Rice::detail::Abstract_Caster * Rice::Data_Type<T>::
257
- caster() const
258
- {
259
- check_is_bound();
260
- return caster_.get();
261
- }
268
+ detail::verifyType<typename Native_T::Native_Return_T>();
262
269
 
263
- namespace Rice
264
- {
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
+ }
265
275
 
266
- template<>
267
- inline detail::Abstract_Caster * Data_Type<void>::
268
- caster() const
269
- {
270
- return 0;
271
- }
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
+ }
272
282
 
273
- template<typename T>
274
- void Data_Type<T>::
275
- check_is_bound()
276
- {
277
- if(!is_bound())
278
- {
279
- std::string s;
280
- s = "Data type ";
281
- s += detail::demangle(typeid(T).name());
282
- s += " is not bound";
283
- throw std::runtime_error(s.c_str());
283
+ detail::MethodData::define_method( klass_, Identifier(name + "=").id(),
284
+ RUBY_METHOD_FUNC(&Native_T::set), 1, native);
285
+ }
286
+
287
+ return *this;
284
288
  }
285
- }
286
289
 
287
- } // Rice
290
+ 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)
293
+ {
294
+ auto* native = detail::Make_Native_Attribute(attr, access);
295
+ using Native_T = typename std::remove_pointer_t<decltype(native)>;
288
296
 
289
- template<typename T>
290
- inline Rice::Data_Type<T> Rice::
291
- define_class_under(
292
- Object module,
293
- char const * name)
294
- {
295
- Class c(define_class_under(module, name, rb_cObject));
296
- c.undef_creation_funcs();
297
- return Data_Type<T>::template bind<void>(c);
298
- }
297
+ detail::verifyType<typename Native_T::Native_Return_T>();
299
298
 
300
- template<typename T, typename Base_T>
301
- inline Rice::Data_Type<T> Rice::
302
- define_class_under(
303
- Object module,
304
- char const * name)
305
- {
306
- Data_Type<Base_T> base_dt;
307
- Class c(define_class_under(module, name, base_dt));
308
- c.undef_creation_funcs();
309
- return Data_Type<T>::template bind<Base_T>(c);
310
- }
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
+ }
311
305
 
312
- template<typename T>
313
- inline Rice::Data_Type<T> Rice::
314
- define_class(
315
- char const * name)
316
- {
317
- Class c(define_class(name, rb_cObject));
318
- c.undef_creation_funcs();
319
- return Data_Type<T>::template bind<void>(c);
320
- }
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
+ }
321
312
 
322
- template<typename T, typename Base_T>
323
- inline Rice::Data_Type<T> Rice::
324
- define_class(
325
- char const * name)
326
- {
327
- Data_Type<Base_T> base_dt;
328
- Class c(define_class(name, base_dt));
329
- c.undef_creation_funcs();
330
- return Data_Type<T>::template bind<Base_T>(c);
331
- }
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
+ }
332
317
 
333
- template<typename From_T, typename To_T>
334
- inline void
335
- Rice::define_implicit_cast()
336
- {
337
- // As Rice currently expects only one entry into
338
- // this list for a given klass VALUE, we need to get
339
- // the current caster for From_T and insert in our
340
- // new caster as the head of the caster list
341
-
342
- Class from_class = Data_Type<From_T>::klass().value();
343
- Class to_class = Data_Type<To_T>::klass().value();
344
-
345
- detail::Abstract_Caster* from_caster =
346
- Data_Type<From_T>::caster_.release();
347
-
348
- detail::Abstract_Caster* new_caster =
349
- new detail::Implicit_Caster<To_T, From_T>(from_caster, to_class);
350
-
351
- // Insert our new caster into the list for the from class
352
- Data_Type_Base::casters().erase(from_class);
353
- Data_Type_Base::casters().insert(
354
- std::make_pair(
355
- from_class,
356
- new_caster
357
- )
358
- );
359
-
360
- // And make sure the from_class has direct access to the
361
- // updated caster list
362
- Data_Type<From_T>::caster_.reset(new_caster);
318
+ return *this;
319
+ }
363
320
  }
364
-
365
- #endif // Rice__Data_Type__ipp_
321
+ #endif