rice 4.3.3 → 4.6.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 (237) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +86 -26
  3. data/CMakeLists.txt +31 -0
  4. data/CMakePresets.json +75 -0
  5. data/COPYING +3 -2
  6. data/FindRuby.cmake +437 -0
  7. data/README.md +7 -2
  8. data/Rakefile +12 -5
  9. data/include/rice/rice.hpp +9522 -4426
  10. data/include/rice/stl.hpp +2831 -1198
  11. data/lib/make_rice_headers.rb +79 -0
  12. data/lib/mkmf-rice.rb +40 -94
  13. data/lib/rice/version.rb +3 -0
  14. data/lib/rice.rb +1 -0
  15. data/lib/rubygems/builder.rb +11 -0
  16. data/lib/rubygems/cmake_builder.rb +113 -0
  17. data/lib/rubygems_plugin.rb +9 -0
  18. data/rice/Address_Registration_Guard.hpp +72 -3
  19. data/rice/Arg.hpp +26 -6
  20. data/rice/Arg.ipp +35 -2
  21. data/rice/Buffer.hpp +123 -0
  22. data/rice/Buffer.ipp +599 -0
  23. data/rice/Callback.hpp +21 -0
  24. data/rice/Callback.ipp +13 -0
  25. data/rice/Constructor.hpp +4 -27
  26. data/rice/Constructor.ipp +79 -0
  27. data/rice/Data_Object.hpp +73 -3
  28. data/rice/Data_Object.ipp +388 -96
  29. data/rice/Data_Type.hpp +214 -3
  30. data/rice/Data_Type.ipp +144 -67
  31. data/rice/Director.hpp +0 -2
  32. data/rice/Enum.hpp +4 -7
  33. data/rice/Enum.ipp +102 -55
  34. data/rice/Exception.hpp +62 -2
  35. data/rice/Exception.ipp +7 -12
  36. data/rice/Init.hpp +8 -0
  37. data/rice/Init.ipp +8 -0
  38. data/rice/JumpException.hpp +44 -0
  39. data/rice/JumpException.ipp +48 -0
  40. data/rice/MemoryView.hpp +11 -0
  41. data/rice/MemoryView.ipp +3 -0
  42. data/rice/Return.hpp +7 -27
  43. data/rice/Return.ipp +13 -13
  44. data/rice/cpp_api/Array.hpp +209 -0
  45. data/rice/cpp_api/Array.ipp +304 -0
  46. data/rice/cpp_api/Builtin_Object.hpp +31 -0
  47. data/rice/cpp_api/Builtin_Object.ipp +37 -0
  48. data/rice/cpp_api/Class.hpp +70 -0
  49. data/rice/cpp_api/Class.ipp +97 -0
  50. data/rice/cpp_api/Encoding.hpp +32 -0
  51. data/rice/cpp_api/Encoding.ipp +59 -0
  52. data/rice/cpp_api/Hash.hpp +194 -0
  53. data/rice/cpp_api/Hash.ipp +257 -0
  54. data/rice/{Identifier.hpp → cpp_api/Identifier.hpp} +2 -6
  55. data/rice/{Identifier.ipp → cpp_api/Identifier.ipp} +4 -2
  56. data/rice/cpp_api/Module.hpp +72 -0
  57. data/rice/cpp_api/Module.ipp +101 -0
  58. data/rice/cpp_api/Object.hpp +272 -0
  59. data/rice/cpp_api/Object.ipp +235 -0
  60. data/rice/cpp_api/String.hpp +74 -0
  61. data/rice/cpp_api/String.ipp +120 -0
  62. data/rice/cpp_api/Struct.hpp +113 -0
  63. data/rice/cpp_api/Struct.ipp +92 -0
  64. data/rice/cpp_api/Symbol.hpp +46 -0
  65. data/rice/cpp_api/Symbol.ipp +93 -0
  66. data/rice/cpp_api/shared_methods.hpp +134 -0
  67. data/rice/detail/DefaultHandler.hpp +12 -0
  68. data/rice/detail/DefaultHandler.ipp +8 -0
  69. data/rice/detail/HandlerRegistry.hpp +5 -35
  70. data/rice/detail/HandlerRegistry.ipp +7 -11
  71. data/rice/detail/InstanceRegistry.hpp +1 -4
  72. data/rice/detail/MethodInfo.hpp +12 -10
  73. data/rice/detail/MethodInfo.ipp +26 -21
  74. data/rice/detail/Native.hpp +33 -0
  75. data/rice/detail/Native.ipp +157 -0
  76. data/rice/detail/NativeAttributeGet.hpp +52 -0
  77. data/rice/detail/NativeAttributeGet.ipp +57 -0
  78. data/rice/detail/NativeAttributeSet.hpp +44 -0
  79. data/rice/detail/NativeAttributeSet.ipp +88 -0
  80. data/rice/detail/NativeCallbackFFI.hpp +55 -0
  81. data/rice/detail/NativeCallbackFFI.ipp +151 -0
  82. data/rice/detail/NativeCallbackSimple.hpp +30 -0
  83. data/rice/detail/NativeCallbackSimple.ipp +29 -0
  84. data/rice/detail/NativeFunction.hpp +33 -23
  85. data/rice/detail/NativeFunction.ipp +309 -70
  86. data/rice/detail/NativeIterator.hpp +9 -11
  87. data/rice/detail/NativeIterator.ipp +33 -31
  88. data/rice/detail/NativeRegistry.hpp +24 -15
  89. data/rice/detail/NativeRegistry.ipp +23 -48
  90. data/rice/detail/Proc.hpp +4 -0
  91. data/rice/detail/Proc.ipp +85 -0
  92. data/rice/detail/Registries.hpp +0 -7
  93. data/rice/detail/Registries.ipp +0 -18
  94. data/rice/detail/RubyFunction.hpp +0 -3
  95. data/rice/detail/RubyFunction.ipp +4 -8
  96. data/rice/detail/RubyType.hpp +16 -0
  97. data/rice/detail/RubyType.ipp +232 -0
  98. data/rice/detail/Type.hpp +7 -6
  99. data/rice/detail/Type.ipp +192 -45
  100. data/rice/detail/TypeRegistry.hpp +15 -7
  101. data/rice/detail/TypeRegistry.ipp +105 -12
  102. data/rice/detail/Wrapper.hpp +68 -32
  103. data/rice/detail/Wrapper.ipp +121 -109
  104. data/rice/detail/cpp_protect.hpp +5 -6
  105. data/rice/detail/default_allocation_func.ipp +0 -2
  106. data/rice/detail/from_ruby.hpp +38 -3
  107. data/rice/detail/from_ruby.ipp +1321 -492
  108. data/rice/detail/ruby.hpp +18 -0
  109. data/rice/detail/to_ruby.hpp +41 -3
  110. data/rice/detail/to_ruby.ipp +1424 -194
  111. data/rice/global_function.hpp +0 -4
  112. data/rice/global_function.ipp +0 -1
  113. data/rice/libc/file.hpp +11 -0
  114. data/rice/libc/file.ipp +32 -0
  115. data/rice/rice.hpp +116 -26
  116. data/rice/ruby_mark.hpp +4 -3
  117. data/rice/stl/complex.hpp +6 -0
  118. data/rice/stl/complex.ipp +93 -0
  119. data/rice/stl/exception.hpp +11 -0
  120. data/rice/stl/exception.ipp +29 -0
  121. data/rice/stl/exception_ptr.hpp +6 -0
  122. data/rice/stl/exception_ptr.ipp +27 -0
  123. data/rice/stl/map.hpp +12 -0
  124. data/rice/stl/map.ipp +469 -0
  125. data/rice/stl/monostate.hpp +6 -0
  126. data/rice/stl/monostate.ipp +80 -0
  127. data/rice/stl/multimap.hpp +14 -0
  128. data/rice/stl/multimap.ipp +448 -0
  129. data/rice/stl/optional.hpp +6 -0
  130. data/rice/stl/optional.ipp +118 -0
  131. data/rice/stl/pair.hpp +13 -0
  132. data/rice/stl/pair.ipp +155 -0
  133. data/rice/stl/reference_wrapper.hpp +6 -0
  134. data/rice/stl/reference_wrapper.ipp +41 -0
  135. data/rice/stl/set.hpp +12 -0
  136. data/rice/stl/set.ipp +495 -0
  137. data/rice/stl/shared_ptr.hpp +28 -0
  138. data/rice/stl/shared_ptr.ipp +224 -0
  139. data/rice/stl/string.hpp +6 -0
  140. data/rice/stl/string.ipp +158 -0
  141. data/rice/stl/string_view.hpp +6 -0
  142. data/rice/stl/string_view.ipp +65 -0
  143. data/rice/stl/tuple.hpp +6 -0
  144. data/rice/stl/tuple.ipp +128 -0
  145. data/rice/stl/type_index.hpp +6 -0
  146. data/rice/stl/type_index.ipp +30 -0
  147. data/rice/stl/type_info.hpp +6 -0
  148. data/rice/stl/type_info.ipp +29 -0
  149. data/rice/stl/unique_ptr.hpp +22 -0
  150. data/rice/stl/unique_ptr.ipp +139 -0
  151. data/rice/stl/unordered_map.hpp +12 -0
  152. data/rice/stl/unordered_map.ipp +469 -0
  153. data/rice/stl/variant.hpp +6 -0
  154. data/rice/stl/variant.ipp +242 -0
  155. data/rice/stl/vector.hpp +12 -0
  156. data/rice/stl/vector.ipp +590 -0
  157. data/rice/stl.hpp +11 -3
  158. data/rice/traits/attribute_traits.hpp +26 -0
  159. data/rice/traits/function_traits.hpp +95 -0
  160. data/rice/traits/method_traits.hpp +47 -0
  161. data/rice/traits/rice_traits.hpp +160 -0
  162. data/rice.gemspec +85 -0
  163. data/test/embed_ruby.cpp +7 -1
  164. data/test/extconf.rb +2 -0
  165. data/test/test_Address_Registration_Guard.cpp +5 -0
  166. data/test/test_Array.cpp +18 -4
  167. data/test/test_Attribute.cpp +136 -21
  168. data/test/test_Buffer.cpp +285 -0
  169. data/test/test_Builtin_Object.cpp +5 -0
  170. data/test/test_Callback.cpp +230 -0
  171. data/test/test_Class.cpp +5 -31
  172. data/test/test_Constructor.cpp +69 -6
  173. data/test/test_Data_Object.cpp +97 -38
  174. data/test/test_Data_Type.cpp +470 -65
  175. data/test/test_Director.cpp +17 -8
  176. data/test/test_Enum.cpp +155 -40
  177. data/test/test_Exception.cpp +235 -0
  178. data/test/test_File.cpp +70 -0
  179. data/test/test_From_Ruby.cpp +609 -0
  180. data/test/test_Hash.cpp +5 -0
  181. data/test/test_Identifier.cpp +5 -0
  182. data/test/test_Inheritance.cpp +6 -1
  183. data/test/test_Iterator.cpp +6 -1
  184. data/test/test_Jump_Exception.cpp +23 -0
  185. data/test/test_Keep_Alive.cpp +13 -19
  186. data/test/test_Keep_Alive_No_Wrapper.cpp +5 -1
  187. data/test/test_Memory_Management.cpp +5 -0
  188. data/test/test_Module.cpp +128 -67
  189. data/test/test_Native_Registry.cpp +2 -34
  190. data/test/test_Object.cpp +5 -0
  191. data/test/test_Overloads.cpp +806 -0
  192. data/test/test_Ownership.cpp +160 -54
  193. data/test/test_Proc.cpp +44 -0
  194. data/test/test_Self.cpp +9 -4
  195. data/test/test_Stl_Exception.cpp +109 -0
  196. data/test/test_Stl_Map.cpp +54 -42
  197. data/test/test_Stl_Multimap.cpp +693 -0
  198. data/test/test_Stl_Optional.cpp +5 -0
  199. data/test/test_Stl_Pair.cpp +14 -9
  200. data/test/test_Stl_Reference_Wrapper.cpp +9 -2
  201. data/test/test_Stl_Set.cpp +790 -0
  202. data/test/test_Stl_SharedPtr.cpp +458 -0
  203. data/test/test_Stl_String.cpp +5 -0
  204. data/test/test_Stl_String_View.cpp +5 -0
  205. data/test/test_Stl_Tuple.cpp +116 -0
  206. data/test/test_Stl_Type.cpp +147 -0
  207. data/test/test_Stl_UniquePtr.cpp +202 -0
  208. data/test/test_Stl_Unordered_Map.cpp +43 -38
  209. data/test/test_Stl_Variant.cpp +217 -84
  210. data/test/test_Stl_Vector.cpp +306 -58
  211. data/test/test_String.cpp +5 -0
  212. data/test/test_Struct.cpp +5 -0
  213. data/test/test_Symbol.cpp +5 -0
  214. data/test/test_Template.cpp +192 -0
  215. data/test/test_To_Ruby.cpp +524 -0
  216. data/test/test_Tracking.cpp +1 -0
  217. data/test/test_Type.cpp +171 -0
  218. data/test/test_global_functions.cpp +67 -7
  219. data/test/unittest.cpp +8 -0
  220. metadata +127 -26
  221. data/lib/version.rb +0 -3
  222. data/rice/Address_Registration_Guard_defn.hpp +0 -79
  223. data/rice/Data_Object_defn.hpp +0 -84
  224. data/rice/Data_Type_defn.hpp +0 -190
  225. data/rice/Exception_defn.hpp +0 -68
  226. data/rice/HandlerRegistration.hpp +0 -15
  227. data/rice/detail/ExceptionHandler.hpp +0 -8
  228. data/rice/detail/ExceptionHandler.ipp +0 -28
  229. data/rice/detail/ExceptionHandler_defn.hpp +0 -77
  230. data/rice/detail/Jump_Tag.hpp +0 -21
  231. data/rice/detail/NativeAttribute.hpp +0 -64
  232. data/rice/detail/NativeAttribute.ipp +0 -112
  233. data/rice/detail/from_ruby_defn.hpp +0 -38
  234. data/rice/detail/to_ruby_defn.hpp +0 -48
  235. data/test/test_Jump_Tag.cpp +0 -17
  236. data/test/test_Stl_SmartPointer.cpp +0 -283
  237. data/test/test_To_From_Ruby.cpp +0 -399
@@ -2,34 +2,21 @@
2
2
  #include <functional>
3
3
  #include <type_traits>
4
4
 
5
- #include "cpp_protect.hpp"
6
- #include "NativeRegistry.hpp"
7
-
8
5
  namespace Rice::detail
9
6
  {
10
7
  template <typename T, typename Iterator_Func_T>
11
8
  inline void NativeIterator<T, Iterator_Func_T>::define(VALUE klass, std::string method_name, Iterator_Func_T begin, Iterator_Func_T end)
12
9
  {
13
- // Tell Ruby to invoke the static method call on this class
14
- detail::protect(rb_define_method, klass, method_name.c_str(), (RUBY_METHOD_FUNC)&NativeIterator_T::call, 0);
15
-
16
- // Now create a NativeIterator instance and save it to the natives registry keyed on
17
- // Ruby klass and method id. There may be multiple NativeIterator instances
18
- // because the same C++ method could be mapped to multiple Ruby methods.
19
- NativeIterator_T* native = new NativeIterator_T(klass, method_name, begin, end);
20
- detail::Registries::instance.natives.add(klass, Identifier(method_name).id(), native);
21
- }
10
+ // Tell Ruby to invoke the resolveIterator static method defined in Native super class.
11
+ detail::protect(rb_define_method, klass, method_name.c_str(), (RUBY_METHOD_FUNC)&Native::resolve, -1);
22
12
 
23
- template<typename T, typename Iterator_Func_T>
24
- inline VALUE NativeIterator<T, Iterator_Func_T>::call(VALUE self)
25
- {
26
- // Look up the native function based on the Ruby klass and method id
27
- NativeIterator_T* nativeIterator = detail::Registries::instance.natives.lookup<NativeIterator_T*>();
13
+ // Create a NativeIterator instance and save it to the NativeRegistry. There may be multiple
14
+ // NativeFunction instances for a specific method because C++ supports method overloading.
15
+ NativeIterator_T* nativeIterator = new NativeIterator_T(klass, method_name, begin, end);
16
+ std::unique_ptr<Native> native(nativeIterator);
28
17
 
29
- return cpp_protect([&]
30
- {
31
- return nativeIterator->operator()(self);
32
- });
18
+ Identifier identifier(method_name);
19
+ detail::Registries::instance.natives.add(klass, identifier.id(), native);
33
20
  }
34
21
 
35
22
  template <typename T, typename Iterator_Func_T>
@@ -38,6 +25,12 @@ namespace Rice::detail
38
25
  {
39
26
  }
40
27
 
28
+ template<typename T, typename Iterator_Func_T>
29
+ inline Resolved NativeIterator<T, Iterator_Func_T>::matches(size_t argc, const VALUE* argv, VALUE self)
30
+ {
31
+ return Resolved{ Convertible::Exact, 1.0, this };
32
+ }
33
+
41
34
  template<typename T, typename Iterator_Func_T>
42
35
  inline VALUE NativeIterator<T, Iterator_Func_T>::createRubyEnumerator(VALUE self)
43
36
  {
@@ -48,12 +41,13 @@ namespace Rice::detail
48
41
  return cpp_protect([&]
49
42
  {
50
43
  // Get the iterator instance
51
- using Iter_T = NativeIterator<T, Iterator_Func_T>;
52
44
  // Class is easy
53
45
  VALUE klass = protect(rb_class_of, recv);
54
46
  // Read the method_id from an attribute we added to the enumerator instance
55
- ID method_id = protect(rb_ivar_get, eobj, rb_intern("rice_method"));
56
- Iter_T* iterator = detail::Registries::instance.natives.lookup<Iter_T*>(klass, method_id);
47
+ Identifier identifier = protect(rb_ivar_get, eobj, rb_intern("rice_method"));
48
+
49
+ const std::vector<std::unique_ptr<Native>>& natives = detail::Registries::instance.natives.lookup(klass, identifier.id());
50
+ NativeIterator_T* iterator = static_cast<NativeIterator_T*>(natives.back().get());
57
51
 
58
52
  // Get the wrapped C++ instance
59
53
  T* receiver = detail::From_Ruby<T*>().convert(recv);
@@ -67,19 +61,18 @@ namespace Rice::detail
67
61
  });
68
62
  };
69
63
 
70
- VALUE method_sym = Identifier(this->method_name_).to_sym();
71
- VALUE enumerator = protect(rb_enumeratorize_with_size, self, method_sym, 0, nullptr, rb_size_function);
64
+ Identifier identifier(this->method_name_);
65
+ VALUE enumerator = protect(rb_enumeratorize_with_size, self, identifier.to_sym(), 0, nullptr, rb_size_function);
72
66
 
73
67
  // Hack the enumerator object by storing name_ on the enumerator object so
74
68
  // the rb_size_function above has access to it
75
- ID method_id = Identifier(this->method_name_).id();
76
- protect(rb_ivar_set, enumerator, rb_intern("rice_method"), method_id);
69
+ protect(rb_ivar_set, enumerator, rb_intern("rice_method"), identifier.id());
77
70
 
78
71
  return enumerator;
79
72
  }
80
73
 
81
74
  template<typename T, typename Iterator_Func_T>
82
- inline VALUE NativeIterator<T, Iterator_Func_T>::operator()(VALUE self)
75
+ inline VALUE NativeIterator<T, Iterator_Func_T>::operator()(size_t argc, const VALUE* argv, VALUE self)
83
76
  {
84
77
  if (!protect(rb_block_given_p))
85
78
  {
@@ -87,16 +80,25 @@ namespace Rice::detail
87
80
  }
88
81
  else
89
82
  {
90
- T* receiver = detail::From_Ruby<T*>().convert(self);
83
+ detail::From_Ruby<T*> fromRuby;
84
+ T* receiver = fromRuby.convert(self);
85
+
91
86
  Iterator_T it = std::invoke(this->begin_, *receiver);
92
87
  Iterator_T end = std::invoke(this->end_, *receiver);
93
88
 
89
+ detail::To_Ruby<To_Ruby_T> toRuby;
94
90
  for (; it != end; ++it)
95
91
  {
96
- protect(rb_yield, detail::To_Ruby<Value_T&>().convert(*it));
92
+ protect(rb_yield, toRuby.convert(*it));
97
93
  }
98
94
 
99
95
  return self;
100
96
  }
101
97
  }
98
+
99
+ template<typename T, typename Iterator_Func_T>
100
+ inline std::string NativeIterator<T, Iterator_Func_T>::toString()
101
+ {
102
+ return "";
103
+ }
102
104
  }
@@ -1,30 +1,39 @@
1
1
  #ifndef Rice__detail__NativeRegistry__hpp
2
2
  #define Rice__detail__NativeRegistry__hpp
3
3
 
4
- #include <unordered_map>
5
- #include <any>
6
-
7
- #include "ruby.hpp"
4
+ #include <map>
5
+ #include <memory>
6
+ #include <utility>
8
7
 
8
+ /* The Native Registry tracks C++ instance that are used to invoke C++ methods for Ruby.
9
+ These objects include instances of the NativeFunction, NativeIterator, NativeAttributeGet
10
+ and NativeAttributeSet Each instance is specialized to call a specific C++ function, method
11
+ or attribute that is exposed to Ruby.
12
+
13
+ The registry stores these C++ instances using a map of vectors. The map is keyed on the
14
+ the Ruby class (VALUE) and method id (ID). The value is a vector of Native pointers stored
15
+ in a std::unique_ptr. Thus the registry takes ownership of the pointers when calling
16
+ code adds them to the registry. The value is a vector to support C++ method overloading.
17
+
18
+ Note - when an existing Ruby class is redefined using rb_define_class, its VALUE stays the same
19
+ but all its methods and fields are reset. Thus any call to rb_define_class must be followed
20
+ by calling the reset method on the registry. Although redefinition shouldn't happen in
21
+ production code it happens in many places in the unit tests. */
22
+
9
23
  namespace Rice::detail
10
24
  {
11
25
  class NativeRegistry
12
26
  {
13
27
  public:
14
- // Add a new native callable object keyed by Ruby class and method_id
15
- void add(VALUE klass, ID method_id, std::any callable);
16
-
17
- // Returns the Rice data for the currently active Ruby method
18
- template <typename Return_T>
19
- Return_T lookup();
20
-
21
- template <typename Return_T>
22
- Return_T lookup(VALUE klass, ID method_id);
28
+ void add(VALUE klass, ID methodId, std::unique_ptr<Native>& native);
29
+ void reset(VALUE klass);
30
+ const std::vector<std::unique_ptr<Native>>& lookup(VALUE klass, ID methodId);
23
31
 
24
32
  private:
25
- std::unordered_multimap<ID, std::pair<VALUE, std::any>> natives_ = {};
33
+ // Key - Ruby klass/method
34
+ // Value - Vector of Native pointers owned by the registry (thus wrapped in std::unique_ptr)
35
+ std::map<std::pair<VALUE, ID>, std::vector<std::unique_ptr<Native>>> natives_ = {};
26
36
  };
27
37
  }
28
- #include "NativeRegistry.ipp"
29
38
 
30
39
  #endif // Rice__detail__NativeRegistry__hpp
@@ -1,74 +1,49 @@
1
1
 
2
- // Ruby 2.7 now includes a similarly named macro that uses templates to
3
- // pick the right overload for the underlying function. That doesn't work
4
- // for our cases because we are using this method dynamically and get a
5
- // compilation error otherwise. This removes the macro and lets us fall
6
- // back to the C-API underneath again.
7
- #undef rb_define_method_id
8
-
9
- #include "RubyFunction.hpp"
10
-
11
2
  namespace Rice::detail
12
3
  {
13
- inline void NativeRegistry::add(VALUE klass, ID method_id, std::any callable)
4
+ inline void NativeRegistry::add(VALUE klass, ID methodId, std::unique_ptr<Native>& native)
14
5
  {
15
6
  if (rb_type(klass) == T_ICLASS)
16
7
  {
17
8
  klass = detail::protect(rb_class_of, klass);
18
9
  }
19
10
 
20
- auto range = this->natives_.equal_range(method_id);
21
- for (auto it = range.first; it != range.second; ++it)
22
- {
23
- const auto [k, d] = it->second;
11
+ // Create the key
12
+ std::pair<VALUE, ID> key = std::make_pair(klass, methodId);
24
13
 
25
- if (k == klass)
26
- {
27
- std::get<1>(it->second) = callable;
28
- return;
29
- }
30
- }
14
+ // Lookup items for method
15
+ std::vector<std::unique_ptr<Native>>& natives = this->natives_[key];
31
16
 
32
- this->natives_.emplace(std::make_pair(method_id, std::make_pair(klass, callable)));
17
+ natives.push_back(std::move(native));
33
18
  }
34
19
 
35
- template <typename Return_T>
36
- inline Return_T NativeRegistry::lookup()
20
+ inline void NativeRegistry::reset(VALUE klass)
37
21
  {
38
- ID method_id;
39
- VALUE klass;
40
- if (!rb_frame_method_id_and_class(&method_id, &klass))
22
+ for (auto iter = this->natives_.begin(); iter != this->natives_.end();)
41
23
  {
42
- rb_raise(rb_eRuntimeError, "Cannot get method id and class for function");
24
+ // Iter points to a std::pair<std::pair<VALUE, ID>, std::vector<NativeRegistryItem>
25
+ if (iter->first.first == klass)
26
+ {
27
+ iter = this->natives_.erase(iter);
28
+ }
29
+ else
30
+ {
31
+ ++iter;
32
+ }
43
33
  }
44
-
45
- return this->lookup<Return_T>(klass, method_id);
46
34
  }
47
-
48
- template <typename Return_T>
49
- inline Return_T NativeRegistry::lookup(VALUE klass, ID method_id)
35
+
36
+ inline const std::vector<std::unique_ptr<Native>>& NativeRegistry::lookup(VALUE klass, ID methodId)
50
37
  {
51
38
  if (rb_type(klass) == T_ICLASS)
52
39
  {
53
40
  klass = detail::protect(rb_class_of, klass);
54
41
  }
55
42
 
56
- auto range = this->natives_.equal_range(method_id);
57
- for (auto it = range.first; it != range.second; ++it)
58
- {
59
- const auto [k, d] = it->second;
60
-
61
- if (k == klass)
62
- {
63
- auto* ptr = std::any_cast<Return_T>(&d);
64
- if (!ptr)
65
- {
66
- rb_raise(rb_eRuntimeError, "Unexpected return type for %s#%s", rb_class2name(klass), rb_id2name(method_id));
67
- }
68
- return *ptr;
69
- }
70
- }
43
+ // Create the key
44
+ std::pair<VALUE, ID> key = std::make_pair(klass, methodId);
71
45
 
72
- rb_raise(rb_eRuntimeError, "Could not find data for klass and method id");
46
+ // Lookup items for method
47
+ return this->natives_[key];
73
48
  }
74
49
  }
@@ -0,0 +1,4 @@
1
+ #ifndef Rice__Proc__hpp_
2
+ #define Rice__Proc__hpp_
3
+
4
+ #endif // Rice__Proc__hpp_
@@ -0,0 +1,85 @@
1
+ namespace Rice::detail
2
+ {
3
+ // Note Return_T(Arg_Ts...) is intentional versus Return_T(*)(Arg_Ts...). That is
4
+ // because the Type machinery strips all pointers/references/const/val etc to avoid
5
+ // having an explosion of Type definitions
6
+ template<typename Return_T, typename ...Arg_Ts>
7
+ struct Type<Return_T(Arg_Ts...)>
8
+ {
9
+ static bool verify()
10
+ {
11
+ return true;
12
+ }
13
+ };
14
+
15
+ // Wraps a C++ function as a Ruby proc
16
+ template<typename Return_T, typename ...Arg_Ts>
17
+ class To_Ruby<Return_T(*)(Arg_Ts...)>
18
+ {
19
+ public:
20
+ using Proc_T = Return_T(*)(Arg_Ts...);
21
+
22
+ VALUE convert(Proc_T proc)
23
+ {
24
+ using NativeFunction_T = NativeFunction<void, Proc_T, false>;
25
+ auto native = new NativeFunction_T(proc);
26
+ VALUE result = rb_proc_new(NativeFunction_T::procEntry, (VALUE)native);
27
+
28
+ // Tie the lifetime of the NativeCallback C++ instance to the lifetime of the Ruby proc object
29
+ VALUE finalizer = rb_proc_new(NativeFunction_T::finalizerCallback, (VALUE)native);
30
+ rb_define_finalizer(result, finalizer);
31
+
32
+ return result;
33
+ }
34
+ };
35
+
36
+ // Makes a Ruby proc callable as C callback
37
+ template<typename Return_T, typename ...Arg_Ts>
38
+ class From_Ruby<Return_T(*)(Arg_Ts...)>
39
+ {
40
+ public:
41
+ using Callback_T = Return_T(*)(Arg_Ts...);
42
+
43
+ From_Ruby() = default;
44
+
45
+ explicit From_Ruby(Arg* arg) : arg_(arg)
46
+ {
47
+ }
48
+
49
+ Convertible is_convertible(VALUE value)
50
+ {
51
+ if (protect(rb_obj_is_proc, value) == Qtrue || protect(rb_proc_lambda_p, value))
52
+ {
53
+ return Convertible::Exact;
54
+ }
55
+ else
56
+ {
57
+ return Convertible::None;
58
+ }
59
+ }
60
+
61
+ #ifdef HAVE_LIBFFI
62
+ Callback_T convert(VALUE value)
63
+ {
64
+ using NativeCallback_T = NativeCallbackFFI<Return_T(*)(Arg_Ts...)>;
65
+ NativeCallback_T* nativeCallback = new NativeCallback_T(value);
66
+
67
+ // Tie the lifetime of the NativeCallback C++ instance to the lifetime of the Ruby proc object
68
+ VALUE finalizer = rb_proc_new(NativeCallback_T::finalizerCallback, (VALUE)nativeCallback);
69
+ rb_define_finalizer(value, finalizer);
70
+
71
+ return nativeCallback->callback();
72
+ }
73
+ #else
74
+ Callback_T convert(VALUE value)
75
+ {
76
+ using NativeCallback_T = NativeCallbackSimple<Return_T(*)(Arg_Ts...)>;
77
+ NativeCallback_T::proc = value;
78
+ return &NativeCallback_T::callback;
79
+ }
80
+ #endif
81
+
82
+ private:
83
+ Arg* arg_ = nullptr;
84
+ };
85
+ }
@@ -1,11 +1,6 @@
1
1
  #ifndef Rice__Registries__hpp_
2
2
  #define Rice__Registries__hpp_
3
3
 
4
- #include "HandlerRegistry.hpp"
5
- #include "InstanceRegistry.hpp"
6
- #include "NativeRegistry.hpp"
7
- #include "TypeRegistry.hpp"
8
-
9
4
  namespace Rice::detail
10
5
  {
11
6
  class Registries
@@ -21,6 +16,4 @@ namespace Rice::detail
21
16
  };
22
17
  }
23
18
 
24
- #include "Registries.ipp"
25
-
26
19
  #endif // Rice__Registries__hpp_
@@ -2,22 +2,4 @@ namespace Rice::detail
2
2
  {
3
3
  //Initialize static variables here.
4
4
  inline Registries Registries::instance;
5
-
6
- // TODO - Big hack here but this code is dependent on internals
7
- template<typename T>
8
- bool Type<T>::verify()
9
- {
10
- // Use intrinsic_type so that we don't have to define specializations
11
- // for pointers, references, const, etc.
12
- using Intrinsic_T = intrinsic_type<T>;
13
-
14
- if constexpr (std::is_fundamental_v<Intrinsic_T>)
15
- {
16
- return true;
17
- }
18
- else
19
- {
20
- return Registries::instance.types.verifyDefined<Intrinsic_T>();
21
- }
22
- }
23
5
  }
@@ -1,8 +1,6 @@
1
1
  #ifndef Rice__detail__ruby_function__hpp_
2
2
  #define Rice__detail__ruby_function__hpp_
3
3
 
4
- #include "ruby.hpp"
5
-
6
4
  namespace Rice::detail
7
5
  {
8
6
  /* This is functor class that wraps calls to a Ruby C API method. It is needed because
@@ -29,6 +27,5 @@ namespace Rice::detail
29
27
  template<typename Function_T, typename ...Arg_Ts>
30
28
  auto protect(Function_T func, Arg_Ts...args);
31
29
  }
32
- #include "RubyFunction.ipp"
33
30
 
34
31
  #endif // Rice__detail__ruby_function__hpp_
@@ -1,5 +1,3 @@
1
- #include "Jump_Tag.hpp"
2
- #include "../Exception_defn.hpp"
3
1
 
4
2
  #include <any>
5
3
 
@@ -14,9 +12,6 @@ namespace Rice::detail
14
12
  template<typename Function_T, typename...Arg_Ts>
15
13
  inline typename RubyFunction<Function_T, Arg_Ts...>::Return_T RubyFunction<Function_T, Arg_Ts...>::operator()()
16
14
  {
17
- const int TAG_RAISE = 0x6; // From Ruby header files
18
- int state = 0;
19
-
20
15
  // Setup a thread local variable to capture the result of the Ruby function call.
21
16
  // We use thread_local because the lambda has to be captureless so it can
22
17
  // be converted to a function pointer callable by C.
@@ -45,10 +40,11 @@ namespace Rice::detail
45
40
  };
46
41
 
47
42
  // Now call rb_protect which will invoke the callback lambda above
43
+ int state = (int)JumpException::RUBY_TAG_NONE;
48
44
  rb_protect(callback, (VALUE)this, &state);
49
45
 
50
46
  // Did anything go wrong?
51
- if (state == 0)
47
+ if (state == JumpException::RUBY_TAG_NONE)
52
48
  {
53
49
  if constexpr (!std::is_same_v<Return_T, void>)
54
50
  {
@@ -58,14 +54,14 @@ namespace Rice::detail
58
54
  else
59
55
  {
60
56
  VALUE err = rb_errinfo();
61
- if (state == TAG_RAISE && RB_TEST(err))
57
+ if (state == JumpException::RUBY_TAG_RAISE && RB_TEST(err))
62
58
  {
63
59
  rb_set_errinfo(Qnil);
64
60
  throw Rice::Exception(err);
65
61
  }
66
62
  else
67
63
  {
68
- throw Jump_Tag(state);
64
+ throw Rice::JumpException((Rice::JumpException::ruby_tag_type)state);
69
65
  }
70
66
  }
71
67
  }
@@ -0,0 +1,16 @@
1
+ #ifndef Rice__detail__ruby__type__hpp_
2
+ #define Rice__detail__ruby__type__hpp_
3
+
4
+ #include <set>
5
+
6
+ namespace Rice::detail
7
+ {
8
+ template <typename T>
9
+ class RubyType
10
+ {
11
+ };
12
+
13
+ void define_ruby_types();
14
+ }
15
+
16
+ #endif // Rice__detail__ruby__type__hpp_