rice 2.1.1 → 4.0.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 (246) 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 +69 -0
  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 -274
  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 +117 -137
  128. data/Doxyfile +0 -2280
  129. data/Makefile.am +0 -26
  130. data/Makefile.in +0 -920
  131. data/README +0 -1055
  132. data/README.mingw +0 -8
  133. data/aclocal.m4 +0 -1088
  134. data/bootstrap +0 -8
  135. data/check_stdcxx_11.ac +0 -142
  136. data/config.guess +0 -1421
  137. data/config.sub +0 -1807
  138. data/configure +0 -7481
  139. data/configure.ac +0 -55
  140. data/depcomp +0 -791
  141. data/doxygen.ac +0 -314
  142. data/doxygen.am +0 -186
  143. data/extconf.rb +0 -69
  144. data/install-sh +0 -501
  145. data/missing +0 -215
  146. data/post-autoconf.rb +0 -22
  147. data/post-automake.rb +0 -28
  148. data/rice/Address_Registration_Guard.cpp +0 -22
  149. data/rice/Arg_impl.hpp +0 -129
  150. data/rice/Arg_operators.cpp +0 -21
  151. data/rice/Arg_operators.hpp +0 -19
  152. data/rice/Array.hpp +0 -214
  153. data/rice/Array.ipp +0 -256
  154. data/rice/Builtin_Object.hpp +0 -8
  155. data/rice/Builtin_Object.ipp +0 -50
  156. data/rice/Builtin_Object_defn.hpp +0 -50
  157. data/rice/Class.cpp +0 -57
  158. data/rice/Class.hpp +0 -8
  159. data/rice/Class.ipp +0 -6
  160. data/rice/Class_defn.hpp +0 -83
  161. data/rice/Data_Type.cpp +0 -54
  162. data/rice/Data_Type_fwd.hpp +0 -12
  163. data/rice/Director.cpp +0 -13
  164. data/rice/Exception.cpp +0 -59
  165. data/rice/Exception_Base.hpp +0 -8
  166. data/rice/Exception_Base.ipp +0 -13
  167. data/rice/Exception_Base_defn.hpp +0 -27
  168. data/rice/Hash.hpp +0 -227
  169. data/rice/Hash.ipp +0 -329
  170. data/rice/Identifier.cpp +0 -8
  171. data/rice/Jump_Tag.hpp +0 -24
  172. data/rice/Makefile.am +0 -124
  173. data/rice/Makefile.in +0 -839
  174. data/rice/Module.cpp +0 -84
  175. data/rice/Module.hpp +0 -8
  176. data/rice/Module.ipp +0 -6
  177. data/rice/Module_defn.hpp +0 -88
  178. data/rice/Module_impl.hpp +0 -281
  179. data/rice/Module_impl.ipp +0 -345
  180. data/rice/Object.cpp +0 -169
  181. data/rice/Object.hpp +0 -8
  182. data/rice/Object.ipp +0 -19
  183. data/rice/Object_defn.hpp +0 -191
  184. data/rice/Require_Guard.hpp +0 -21
  185. data/rice/String.cpp +0 -94
  186. data/rice/String.hpp +0 -91
  187. data/rice/Struct.cpp +0 -117
  188. data/rice/Struct.hpp +0 -162
  189. data/rice/Struct.ipp +0 -26
  190. data/rice/Symbol.cpp +0 -25
  191. data/rice/Symbol.hpp +0 -66
  192. data/rice/Symbol.ipp +0 -44
  193. data/rice/config.hpp +0 -47
  194. data/rice/config.hpp.in +0 -46
  195. data/rice/detail/Arguments.hpp +0 -118
  196. data/rice/detail/Auto_Function_Wrapper.hpp +0 -898
  197. data/rice/detail/Auto_Function_Wrapper.ipp +0 -3694
  198. data/rice/detail/Auto_Member_Function_Wrapper.hpp +0 -897
  199. data/rice/detail/Auto_Member_Function_Wrapper.ipp +0 -2774
  200. data/rice/detail/Caster.hpp +0 -103
  201. data/rice/detail/Not_Copyable.hpp +0 -25
  202. data/rice/detail/Wrapped_Function.hpp +0 -33
  203. data/rice/detail/cfp.hpp +0 -24
  204. data/rice/detail/cfp.ipp +0 -51
  205. data/rice/detail/check_ruby_type.cpp +0 -27
  206. data/rice/detail/check_ruby_type.hpp +0 -23
  207. data/rice/detail/creation_funcs.hpp +0 -37
  208. data/rice/detail/creation_funcs.ipp +0 -36
  209. data/rice/detail/define_method_and_auto_wrap.hpp +0 -31
  210. data/rice/detail/define_method_and_auto_wrap.ipp +0 -30
  211. data/rice/detail/demangle.cpp +0 -56
  212. data/rice/detail/demangle.hpp +0 -19
  213. data/rice/detail/env.hpp +0 -11
  214. data/rice/detail/method_data.cpp +0 -86
  215. data/rice/detail/node.hpp +0 -13
  216. data/rice/detail/object_call.hpp +0 -69
  217. data/rice/detail/object_call.ipp +0 -131
  218. data/rice/detail/protect.cpp +0 -29
  219. data/rice/detail/protect.hpp +0 -34
  220. data/rice/detail/ruby_version_code.hpp +0 -6
  221. data/rice/detail/ruby_version_code.hpp.in +0 -6
  222. data/rice/detail/st.hpp +0 -22
  223. data/rice/detail/traits.hpp +0 -43
  224. data/rice/detail/win32.hpp +0 -16
  225. data/rice/detail/wrap_function.hpp +0 -341
  226. data/rice/detail/wrap_function.ipp +0 -514
  227. data/rice/protect.hpp +0 -92
  228. data/rice/protect.ipp +0 -1134
  229. data/rice/rubypp.rb +0 -97
  230. data/rice/to_from_ruby.hpp +0 -8
  231. data/rice/to_from_ruby.ipp +0 -294
  232. data/rice/to_from_ruby_defn.hpp +0 -70
  233. data/ruby.ac +0 -135
  234. data/ruby/Makefile.am +0 -1
  235. data/ruby/Makefile.in +0 -625
  236. data/ruby/lib/Makefile.am +0 -3
  237. data/ruby/lib/Makefile.in +0 -503
  238. data/ruby/lib/mkmf-rice.rb.in +0 -217
  239. data/ruby/lib/version.rb +0 -3
  240. data/sample/Makefile.am +0 -47
  241. data/sample/Makefile.in +0 -486
  242. data/test/Makefile.am +0 -72
  243. data/test/Makefile.in +0 -1150
  244. data/test/ext/Makefile.am +0 -41
  245. data/test/ext/Makefile.in +0 -480
  246. 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