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
@@ -0,0 +1,39 @@
1
+ #ifndef Rice__detail__ruby_function__hpp_
2
+ #define Rice__detail__ruby_function__hpp_
3
+
4
+ #include "ruby.hpp"
5
+
6
+ namespace Rice::detail
7
+ {
8
+ /* This is functor class that wraps calls to a Ruby C API method. It is needed because
9
+ rb_protect only supports calling methods that take one argument. Thus
10
+ we invoke rb_protect telling it to invoke Ruby_Function::call with an
11
+ instance of a Ruby_Function. That instance then in turn calls the original
12
+ Ruby method passing along its required arguments. */
13
+
14
+ template<typename Function_T, typename Return_T, typename...Arg_Ts>
15
+ class RubyFunction
16
+ {
17
+ public:
18
+ RubyFunction(Function_T func, const Arg_Ts&... args);
19
+ Return_T operator()();
20
+
21
+ private:
22
+ Function_T func_;
23
+ std::tuple<Arg_Ts...> args_;
24
+ };
25
+
26
+ template<typename Return_T, typename ...Arg_Ts>
27
+ Return_T protect(Return_T(*func)(Arg_Ts...), Arg_Ts...args);
28
+ }
29
+
30
+ namespace Rice
31
+ {
32
+ template<typename Return_T, typename ...Arg_Ts>
33
+ [[deprecated("Please use detail::protect")]]
34
+ Return_T protect(Return_T(*func)(Arg_Ts...), Arg_Ts...args);
35
+ }
36
+
37
+ #include "RubyFunction.ipp"
38
+
39
+ #endif // Rice__detail__ruby_function__hpp_
@@ -0,0 +1,92 @@
1
+ #include "Jump_Tag.hpp"
2
+ #include "../Exception_defn.hpp"
3
+
4
+ #include <any>
5
+
6
+ namespace Rice::detail
7
+ {
8
+ template<typename Function_T, typename Return_T, typename...Arg_Ts>
9
+ inline RubyFunction<Function_T, Return_T, Arg_Ts...>::RubyFunction(Function_T func, const Arg_Ts&... args)
10
+ : func_(func), args_(std::forward_as_tuple(args...))
11
+ {
12
+ }
13
+
14
+ template<typename Function_T, typename Return_T, typename...Arg_Ts>
15
+ inline Return_T RubyFunction<Function_T, Return_T, Arg_Ts...>::operator()()
16
+ {
17
+ const int TAG_RAISE = 0x6; // From Ruby header files
18
+ int state = 0;
19
+
20
+ // Setup a thread local variable to capture the result of the Ruby function call.
21
+ // We use thread_local because the lambda has to be captureless so it can
22
+ // be converted to a function pointer callable by C.
23
+ // The thread local variable avoids having to cast the result to VALUE and then
24
+ // back again to Return_T. The problem with that is the translation is not lossless
25
+ // in some cases - for example a double with value of -1.0 does not roundrip.
26
+ //
27
+ thread_local std::any result;
28
+
29
+ // Callback that will invoke the Ruby function
30
+ using Functor_T = RubyFunction<Function_T, Return_T, Arg_Ts...>;
31
+ auto callback = [](VALUE value)
32
+ {
33
+ Functor_T* functor = (Functor_T*)value;
34
+
35
+ if constexpr (std::is_same_v<Return_T, void>)
36
+ {
37
+ std::apply(functor->func_, functor->args_);
38
+ }
39
+ else
40
+ {
41
+ result = std::apply(functor->func_, functor->args_);
42
+ }
43
+
44
+ return Qnil;
45
+ };
46
+
47
+ // Now call rb_protect which will invoke the callback lambda above
48
+ rb_protect(callback, (VALUE)this, &state);
49
+
50
+ // Did anything go wrong?
51
+ if (state == 0)
52
+ {
53
+ if constexpr (!std::is_same_v<Return_T, void>)
54
+ {
55
+ return std::any_cast<Return_T>(result);
56
+ }
57
+ }
58
+ else
59
+ {
60
+ VALUE err = rb_errinfo();
61
+ if (state == TAG_RAISE && RTEST(err))
62
+ {
63
+ rb_set_errinfo(Qnil);
64
+ throw Rice::Exception(err);
65
+ }
66
+ else
67
+ {
68
+ throw Jump_Tag(state);
69
+ }
70
+ }
71
+ }
72
+
73
+ // Create a functor for calling a Ruby function and define some aliases for readability.
74
+ template<typename Return_T, typename ...Arg_Ts>
75
+ inline Return_T protect(Return_T(*func)(Arg_Ts...), Arg_Ts...args)
76
+ {
77
+ using Function_T = Return_T(*)(Arg_Ts...);
78
+ auto rubyFunction = RubyFunction<Function_T, Return_T, Arg_Ts...>(func, args...);
79
+ return rubyFunction();
80
+ }
81
+ }
82
+
83
+ namespace Rice
84
+ {
85
+ template<typename Return_T, typename ...Arg_Ts>
86
+ inline Return_T protect(Return_T(*func)(Arg_Ts...), Arg_Ts...args)
87
+ {
88
+ using Function_T = Return_T(*)(Arg_Ts...);
89
+ auto rubyFunction = detail::RubyFunction<Function_T, Return_T, Arg_Ts...>(func, args...);
90
+ return rubyFunction();
91
+ }
92
+ }
@@ -0,0 +1,29 @@
1
+ #ifndef Rice__Type__hpp_
2
+ #define Rice__Type__hpp_
3
+
4
+ #include <string>
5
+ #include <typeinfo>
6
+ #include "rice_traits.hpp"
7
+
8
+ namespace Rice::detail
9
+ {
10
+ template<typename T>
11
+ struct Type
12
+ {
13
+ static bool verify();
14
+ };
15
+
16
+ // Return the name of a type
17
+ std::string typeName(const std::type_info& typeInfo);
18
+ std::string makeClassName(const std::type_info& typeInfo);
19
+
20
+ template<typename T>
21
+ void verifyType();
22
+
23
+ template<typename Tuple_T>
24
+ void verifyTypes();
25
+ }
26
+
27
+ #include "Type.ipp"
28
+
29
+ #endif // Rice__Type__hpp_
@@ -0,0 +1,138 @@
1
+ #include "rice_traits.hpp"
2
+
3
+ #include <iosfwd>
4
+ #include <numeric>
5
+ #include <regex>
6
+ #include <sstream>
7
+ #include <tuple>
8
+
9
+ #ifdef __GNUC__
10
+ #include <cxxabi.h>
11
+ #include <cstdlib>
12
+ #include <cstring>
13
+ #endif
14
+
15
+ namespace Rice::detail
16
+ {
17
+ template<>
18
+ struct Type<void>
19
+ {
20
+ static bool verify()
21
+ {
22
+ return true;
23
+ }
24
+ };
25
+
26
+ template<typename T>
27
+ void verifyType()
28
+ {
29
+ Type<intrinsic_type<T>>::verify();
30
+ }
31
+
32
+ template<typename Tuple_T, size_t...Is>
33
+ void verifyTypesImpl()
34
+ {
35
+ (Type<intrinsic_type<typename std::tuple_element<Is, Tuple_T>::type>>::verify(), ...);
36
+ }
37
+
38
+ template<typename Tuple_T>
39
+ void verifyTypes()
40
+ {
41
+ if constexpr (std::tuple_size<Tuple_T>::value > 0)
42
+ {
43
+ verifyTypesImpl<Tuple_T, std::tuple_size<Tuple_T>::value - 1>();
44
+ }
45
+ }
46
+
47
+ inline std::string demangle(char const* mangled_name)
48
+ {
49
+ #ifdef __GNUC__
50
+ struct Helper
51
+ {
52
+ Helper(
53
+ char const* mangled_name)
54
+ : name_(0)
55
+ {
56
+ int status = 0;
57
+ name_ = abi::__cxa_demangle(mangled_name, 0, 0, &status);
58
+ }
59
+
60
+ ~Helper()
61
+ {
62
+ std::free(name_);
63
+ }
64
+
65
+ char* name_;
66
+
67
+ private:
68
+ Helper(Helper const&);
69
+ void operator=(Helper const&);
70
+ };
71
+
72
+ Helper helper(mangled_name);
73
+ if (helper.name_)
74
+ {
75
+ return helper.name_;
76
+ }
77
+ else
78
+ {
79
+ return mangled_name;
80
+ }
81
+ #else
82
+ return mangled_name;
83
+ #endif
84
+ }
85
+
86
+ inline std::string typeName(const std::type_info& typeInfo)
87
+ {
88
+ return demangle(typeInfo.name());
89
+ }
90
+
91
+ inline std::string makeClassName(const std::type_info& typeInfo)
92
+ {
93
+ std::string base = demangle(typeInfo.name());
94
+
95
+ // Remove class keyword
96
+ auto classRegex = std::regex("class +");
97
+ base = std::regex_replace(base, classRegex, "");
98
+
99
+ // Remove struct keyword
100
+ auto structRegex = std::regex("struct +");
101
+ base = std::regex_replace(base, structRegex, "");
102
+
103
+ // Remove std::__[^:]*::
104
+ auto stdClangRegex = std::regex("std::__[^:]+::");
105
+ base = std::regex_replace(base, stdClangRegex, "");
106
+
107
+ // Remove std::
108
+ auto stdRegex = std::regex("std::");
109
+ base = std::regex_replace(base, stdRegex, "");
110
+
111
+ // Replace > >
112
+ auto trailingAngleBracketSpaceRegex = std::regex(" >");
113
+ base = std::regex_replace(base, trailingAngleBracketSpaceRegex, ">");
114
+
115
+ // Replace < and >
116
+ auto angleBracketRegex = std::regex("<|>");
117
+ base = std::regex_replace(base, angleBracketRegex, "__");
118
+
119
+ // Replace ,
120
+ auto commaRegex = std::regex(", *");
121
+ base = std::regex_replace(base, commaRegex, "_");
122
+
123
+ // Now create a vector of strings split on whitespace
124
+ std::istringstream stream(base);
125
+ std::vector<std::string> words{ std::istream_iterator<std::string>{stream},
126
+ std::istream_iterator<std::string>{} };
127
+
128
+ std::string result = std::accumulate(words.begin(), words.end(), std::string(),
129
+ [](const std::string& memo, const std::string& word) -> std::string
130
+ {
131
+ std::string capitalized = word;
132
+ capitalized[0] = toupper(capitalized[0]);
133
+ return memo + capitalized;
134
+ });
135
+
136
+ return result;
137
+ }
138
+ }
@@ -0,0 +1,50 @@
1
+ #ifndef Rice__TypeRegistry__hpp_
2
+ #define Rice__TypeRegistry__hpp_
3
+
4
+ #include <optional>
5
+ #include <string>
6
+ #include <typeindex>
7
+ #include <typeinfo>
8
+ #include <unordered_map>
9
+
10
+ #include "ruby.hpp"
11
+
12
+ /* The type registery keeps track of all C++ types wrapped by Rice. When a native function returns
13
+ an instance of a class/struct we look up its type to verity that it has been registered.
14
+
15
+ We have to do this to support C++ inheritance. If a C++ function returns a pointer/reference
16
+ to an Abstract class, the actual returned object will be a Child class. However, all we know
17
+ from the C++ method signature is that it is an Absract class - thus the need for a registry.*/
18
+
19
+ namespace Rice::detail
20
+ {
21
+ class TypeRegistry
22
+ {
23
+ public:
24
+ template <typename T>
25
+ static void add();
26
+
27
+ template <typename T>
28
+ static void add(VALUE klass, rb_data_type_t* rbType);
29
+
30
+ template <typename T>
31
+ static void remove();
32
+
33
+ template <typename T>
34
+ static bool isDefined();
35
+
36
+ template <typename T>
37
+ static void verifyDefined();
38
+
39
+ template <typename T>
40
+ static std::pair<VALUE, rb_data_type_t*> figureType(const T& object);
41
+
42
+ private:
43
+ static std::optional<std::pair<VALUE, rb_data_type_t*>> lookup(const std::type_info& typeInfo);
44
+ static inline std::unordered_map<std::type_index, std::pair<VALUE, rb_data_type_t*>> registry_{};
45
+ };
46
+ }
47
+
48
+ #include "TypeRegistry.ipp"
49
+
50
+ #endif // Rice__TypeRegistry__hpp_
@@ -0,0 +1,106 @@
1
+ #include <stdexcept>
2
+
3
+ #include "ruby.hpp"
4
+ #include "rice_traits.hpp"
5
+ #include "Type.hpp"
6
+
7
+ namespace Rice::detail
8
+ {
9
+ template <typename T>
10
+ inline void TypeRegistry::add()
11
+ {
12
+ std::type_index key(typeid(T));
13
+ registry_[key] = std::pair(Qnil, nullptr);
14
+ }
15
+
16
+ template <typename T>
17
+ inline void TypeRegistry::add(VALUE klass, rb_data_type_t* rbType)
18
+ {
19
+ std::type_index key(typeid(T));
20
+ registry_[key] = std::pair(klass, rbType);
21
+ }
22
+
23
+ template <typename T>
24
+ inline void TypeRegistry::remove()
25
+ {
26
+ std::type_index key(typeid(T));
27
+ registry_.erase(key);
28
+ }
29
+
30
+ template <typename T>
31
+ inline bool TypeRegistry::isDefined()
32
+ {
33
+ std::type_index key(typeid(T));
34
+ auto iter = registry_.find(key);
35
+ return iter != registry_.end();
36
+ }
37
+
38
+ template <typename T>
39
+ inline void TypeRegistry::verifyDefined()
40
+ {
41
+ if (!isDefined<T>())
42
+ {
43
+ std::string message = "Type is not defined with Rice: " + detail::typeName(typeid(T));
44
+ throw std::invalid_argument(message);
45
+ }
46
+ }
47
+
48
+ inline std::optional<std::pair<VALUE, rb_data_type_t*>> TypeRegistry::lookup(const std::type_info& typeInfo)
49
+ {
50
+ std::type_index key(typeInfo);
51
+ auto iter = registry_.find(key);
52
+
53
+ if (iter == registry_.end())
54
+ {
55
+ return std::nullopt;
56
+ }
57
+ else
58
+ {
59
+ return iter->second;
60
+ }
61
+ }
62
+
63
+ template <typename T>
64
+ inline std::pair<VALUE, rb_data_type_t*> TypeRegistry::figureType(const T& object)
65
+ {
66
+ // First check and see if the actual type of the object is registered
67
+ std::optional<std::pair<VALUE, rb_data_type_t*>> result = lookup(typeid(object));
68
+
69
+ if (result)
70
+ {
71
+ return result.value();
72
+ }
73
+
74
+ // If not, then we are willing to accept an ancestor class specified by T. This is needed
75
+ // to support Directors. Classes inherited from Directors are never actually registered
76
+ // with Rice - and what we really want it to return the C++ class they inherit from.
77
+ result = lookup(typeid(T));
78
+ if (result)
79
+ {
80
+ return result.value();
81
+ }
82
+
83
+ // Give up!
84
+ std::string message = "Type " + typeName(typeid(object)) + " is not registered";
85
+ throw std::runtime_error(message.c_str());
86
+ }
87
+
88
+ // TODO - hacky to put this here but there is a circular dependency between Type and TypeRegistry
89
+ template<typename T>
90
+ bool Type<T>::verify()
91
+ {
92
+ // Use intrinsic_type so that we don't have to define specializations
93
+ // for pointers, references, const, etc.
94
+ using Intrinsic_T = intrinsic_type<T>;
95
+
96
+ if constexpr (std::is_fundamental_v<Intrinsic_T>)
97
+ {
98
+ return true;
99
+ }
100
+ else
101
+ {
102
+ TypeRegistry::verifyDefined<Intrinsic_T>();
103
+ return true;
104
+ }
105
+ }
106
+ }