rice 4.6.1 → 4.7.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 (187) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +38 -0
  3. data/CMakeLists.txt +0 -4
  4. data/Rakefile +2 -8
  5. data/bin/rice-doc.rb +211 -0
  6. data/bin/rice-rbs.rb +92 -0
  7. data/include/rice/rice.hpp +4694 -3704
  8. data/include/rice/stl.hpp +840 -294
  9. data/lib/rice/doc/cpp_reference.rb +166 -0
  10. data/lib/rice/doc/doxygen.rb +294 -0
  11. data/lib/rice/doc/mkdocs.rb +298 -0
  12. data/lib/rice/doc/rice.rb +29 -0
  13. data/lib/rice/doc/ruby.rb +37 -0
  14. data/lib/rice/doc.rb +5 -0
  15. data/lib/{make_rice_headers.rb → rice/make_rice_headers.rb} +3 -0
  16. data/lib/rice/native.rb +18 -0
  17. data/lib/rice/native_registry.rb +21 -0
  18. data/lib/rice/parameter.rb +7 -0
  19. data/lib/rice/rbs.rb +104 -0
  20. data/lib/rice/version.rb +1 -1
  21. data/lib/rice.rb +4 -0
  22. data/lib/rubygems/cmake_builder.rb +24 -27
  23. data/rice/Arg.hpp +4 -4
  24. data/rice/Arg.ipp +4 -4
  25. data/rice/Buffer.hpp +32 -28
  26. data/rice/Buffer.ipp +306 -178
  27. data/rice/Data_Object.ipp +136 -88
  28. data/rice/Data_Type.hpp +5 -7
  29. data/rice/Data_Type.ipp +48 -29
  30. data/rice/Enum.ipp +15 -21
  31. data/rice/Function.hpp +17 -0
  32. data/rice/Function.ipp +13 -0
  33. data/rice/Pointer.hpp +15 -0
  34. data/rice/Pointer.ipp +49 -0
  35. data/rice/Return.hpp +1 -1
  36. data/rice/Return.ipp +2 -2
  37. data/rice/api.hpp +30 -0
  38. data/rice/cpp_api/Array.hpp +4 -4
  39. data/rice/cpp_api/Array.ipp +50 -5
  40. data/rice/cpp_api/Class.hpp +0 -5
  41. data/rice/cpp_api/Class.ipp +19 -0
  42. data/rice/cpp_api/Hash.ipp +20 -0
  43. data/rice/cpp_api/Module.hpp +6 -3
  44. data/rice/cpp_api/Module.ipp +49 -11
  45. data/rice/cpp_api/Object.ipp +31 -2
  46. data/rice/cpp_api/String.hpp +1 -2
  47. data/rice/cpp_api/String.ipp +21 -1
  48. data/rice/cpp_api/Struct.ipp +5 -0
  49. data/rice/cpp_api/Symbol.ipp +43 -0
  50. data/rice/cpp_api/shared_methods.hpp +12 -12
  51. data/rice/detail/MethodInfo.hpp +4 -2
  52. data/rice/detail/MethodInfo.ipp +19 -3
  53. data/rice/detail/ModuleRegistry.hpp +18 -0
  54. data/rice/detail/ModuleRegistry.ipp +25 -0
  55. data/rice/detail/Native.hpp +45 -2
  56. data/rice/detail/Native.ipp +196 -6
  57. data/rice/detail/NativeAttributeGet.hpp +9 -4
  58. data/rice/detail/NativeAttributeGet.ipp +65 -11
  59. data/rice/detail/NativeAttributeSet.hpp +4 -0
  60. data/rice/detail/NativeAttributeSet.ipp +30 -2
  61. data/rice/detail/NativeCallbackFFI.ipp +2 -2
  62. data/rice/detail/NativeCallbackSimple.ipp +1 -1
  63. data/rice/detail/NativeFunction.hpp +11 -49
  64. data/rice/detail/NativeFunction.ipp +82 -379
  65. data/rice/detail/NativeInvoker.hpp +74 -0
  66. data/rice/detail/NativeInvoker.ipp +197 -0
  67. data/rice/detail/NativeIterator.hpp +4 -0
  68. data/rice/detail/NativeIterator.ipp +19 -0
  69. data/rice/detail/NativeMethod.hpp +97 -0
  70. data/rice/detail/NativeMethod.ipp +332 -0
  71. data/rice/detail/NativeProc.hpp +51 -0
  72. data/rice/detail/NativeProc.ipp +133 -0
  73. data/rice/detail/NativeRegistry.hpp +8 -0
  74. data/rice/detail/NativeRegistry.ipp +26 -0
  75. data/rice/detail/Parameter.hpp +47 -0
  76. data/rice/detail/Parameter.ipp +105 -0
  77. data/rice/detail/Proc.ipp +14 -13
  78. data/rice/detail/Registries.hpp +1 -0
  79. data/rice/detail/RubyType.hpp +0 -2
  80. data/rice/detail/RubyType.ipp +15 -33
  81. data/rice/detail/Type.hpp +44 -8
  82. data/rice/detail/Type.ipp +151 -49
  83. data/rice/detail/TypeRegistry.hpp +3 -0
  84. data/rice/detail/TypeRegistry.ipp +17 -27
  85. data/rice/detail/Types.ipp +430 -0
  86. data/rice/detail/Wrapper.hpp +12 -0
  87. data/rice/detail/Wrapper.ipp +45 -2
  88. data/rice/detail/from_ruby.ipp +567 -1073
  89. data/rice/detail/ruby.hpp +1 -0
  90. data/rice/detail/to_ruby.ipp +4 -635
  91. data/rice/libc/file.ipp +3 -6
  92. data/rice/rice.hpp +22 -12
  93. data/rice/rice_api/Arg.hpp +7 -0
  94. data/rice/rice_api/Arg.ipp +9 -0
  95. data/rice/rice_api/ModuleRegistry.hpp +7 -0
  96. data/rice/rice_api/ModuleRegistry.ipp +10 -0
  97. data/rice/rice_api/Native.hpp +7 -0
  98. data/rice/rice_api/Native.ipp +52 -0
  99. data/rice/rice_api/NativeRegistry.hpp +7 -0
  100. data/rice/rice_api/NativeRegistry.ipp +21 -0
  101. data/rice/rice_api/Parameter.hpp +7 -0
  102. data/rice/rice_api/Parameter.ipp +11 -0
  103. data/rice/rice_api/Registries.hpp +6 -0
  104. data/rice/rice_api/Registries.ipp +12 -0
  105. data/rice/rice_api/TypeRegistry.hpp +7 -0
  106. data/rice/rice_api/TypeRegistry.ipp +10 -0
  107. data/rice/stl/complex.ipp +35 -0
  108. data/rice/stl/exception.ipp +20 -7
  109. data/rice/stl/filesystem.hpp +6 -0
  110. data/rice/stl/filesystem.ipp +34 -0
  111. data/rice/stl/map.ipp +13 -21
  112. data/rice/stl/monostate.ipp +37 -1
  113. data/rice/stl/multimap.ipp +17 -24
  114. data/rice/stl/optional.ipp +47 -2
  115. data/rice/stl/pair.ipp +23 -58
  116. data/rice/stl/reference_wrapper.ipp +22 -1
  117. data/rice/stl/set.ipp +17 -9
  118. data/rice/stl/shared_ptr.ipp +44 -17
  119. data/rice/stl/string.ipp +175 -7
  120. data/rice/stl/string_view.ipp +23 -0
  121. data/rice/stl/tuple.ipp +38 -9
  122. data/rice/stl/unique_ptr.ipp +46 -2
  123. data/rice/stl/unordered_map.ipp +13 -21
  124. data/rice/stl/variant.ipp +47 -11
  125. data/rice/stl/vector.ipp +183 -104
  126. data/rice/stl.hpp +1 -0
  127. data/rice/traits/function_traits.hpp +2 -2
  128. data/rice/traits/method_traits.hpp +5 -16
  129. data/rice/traits/rice_traits.hpp +24 -4
  130. data/rice.gemspec +10 -22
  131. data/test/embed_ruby.cpp +0 -3
  132. data/test/test_Array.cpp +38 -38
  133. data/test/test_Attribute.cpp +187 -2
  134. data/test/test_Buffer.cpp +302 -26
  135. data/test/test_Callback.cpp +2 -3
  136. data/test/test_Class.cpp +5 -5
  137. data/test/test_Data_Object.cpp +1 -56
  138. data/test/test_Data_Type.cpp +20 -30
  139. data/test/test_Enum.cpp +4 -46
  140. data/test/test_From_Ruby.cpp +89 -82
  141. data/test/test_GVL.cpp +109 -0
  142. data/test/test_Iterator.cpp +1 -1
  143. data/test/test_Keep_Alive_No_Wrapper.cpp +5 -3
  144. data/test/test_Module.cpp +8 -9
  145. data/test/test_Object.cpp +1 -1
  146. data/test/test_Overloads.cpp +58 -10
  147. data/test/test_Stl_Map.cpp +8 -8
  148. data/test/test_Stl_Multimap.cpp +4 -4
  149. data/test/test_Stl_Pair.cpp +5 -3
  150. data/test/test_Stl_SharedPtr.cpp +24 -12
  151. data/test/test_Stl_String_View.cpp +10 -0
  152. data/test/test_Stl_Tuple.cpp +1 -1
  153. data/test/test_Stl_UniquePtr.cpp +8 -0
  154. data/test/test_Stl_Unordered_Map.cpp +9 -9
  155. data/test/test_Stl_Variant.cpp +9 -3
  156. data/test/test_Stl_Vector.cpp +118 -13
  157. data/test/test_Symbol.cpp +12 -0
  158. data/test/test_To_Ruby.cpp +35 -28
  159. data/test/test_Type.cpp +256 -53
  160. data/test/unittest.hpp +35 -0
  161. metadata +52 -34
  162. data/rice/Init.hpp +0 -8
  163. data/rice/Init.ipp +0 -8
  164. data/rice/detail/RubyFunction.hpp +0 -31
  165. data/rice/detail/RubyFunction.ipp +0 -77
  166. data/sample/callbacks/extconf.rb +0 -5
  167. data/sample/callbacks/sample_callbacks.cpp +0 -35
  168. data/sample/callbacks/test.rb +0 -28
  169. data/sample/enum/extconf.rb +0 -5
  170. data/sample/enum/sample_enum.cpp +0 -40
  171. data/sample/enum/test.rb +0 -8
  172. data/sample/inheritance/animals.cpp +0 -82
  173. data/sample/inheritance/extconf.rb +0 -5
  174. data/sample/inheritance/test.rb +0 -7
  175. data/sample/map/extconf.rb +0 -5
  176. data/sample/map/map.cpp +0 -73
  177. data/sample/map/test.rb +0 -7
  178. data/test/ext/t1/Foo.hpp +0 -10
  179. data/test/ext/t1/extconf.rb +0 -4
  180. data/test/ext/t1/t1.cpp +0 -13
  181. data/test/ext/t2/extconf.rb +0 -4
  182. data/test/ext/t2/t2.cpp +0 -11
  183. data/test/ruby/test_callbacks_sample.rb +0 -28
  184. data/test/ruby/test_multiple_extensions.rb +0 -18
  185. data/test/ruby/test_multiple_extensions_same_class.rb +0 -14
  186. data/test/ruby/test_multiple_extensions_with_inheritance.rb +0 -20
  187. /data/test/{test_Stl_Type.cpp → test_Stl_Type_Info.cpp} +0 -0
@@ -0,0 +1,51 @@
1
+ #ifndef Rice__detail__Native_Proc__hpp_
2
+ #define Rice__detail__Native_Proc__hpp_
3
+
4
+ namespace Rice::detail
5
+ {
6
+ template<typename Proc_T>
7
+ class NativeProc: Native
8
+ {
9
+ public:
10
+ using NativeProc_T = NativeProc<Proc_T>;
11
+
12
+ // We remove const to avoid an explosion of To_Ruby specializations and Ruby doesn't
13
+ // have the concept of constants anyways
14
+ using Return_T = typename function_traits<Proc_T>::return_type;
15
+ using Arg_Ts = typename function_traits<Proc_T>::arg_types;
16
+ using To_Ruby_T = remove_cv_recursive_t<Return_T>;
17
+
18
+ // Define a new Ruby Proc to wrap a C++ function
19
+ static VALUE createRubyProc(Proc_T proc);
20
+ static NativeProc<Proc_T>* define(Proc_T proc);
21
+
22
+ // This is the method Ruby calls when invoking the proc
23
+ static VALUE resolve(VALUE yielded_arg, VALUE callback_arg, int argc, const VALUE* argv, VALUE blockarg);
24
+
25
+ public:
26
+ NativeProc(Proc_T proc, MethodInfo* methodInfo);
27
+ VALUE operator()(size_t argc, const VALUE* argv, VALUE self) override;
28
+ std::string toString() override;
29
+
30
+ std::string name() override;
31
+ NativeKind kind() override;
32
+ VALUE returnKlass() override;
33
+
34
+ private:
35
+ static VALUE finalizerCallback(VALUE yielded_arg, VALUE callback_arg, int argc, const VALUE* argv, VALUE blockarg);
36
+
37
+ // Convert Ruby values to C++ values
38
+ template<typename std::size_t...I>
39
+ Arg_Ts getNativeValues(std::vector<std::optional<VALUE>>& values, std::index_sequence<I...>& indices);
40
+
41
+ // Call the underlying C++ function
42
+ VALUE invoke(Arg_Ts&& nativeArgs);
43
+
44
+ private:
45
+ Proc_T proc_;
46
+ std::unique_ptr<MethodInfo> methodInfo_;
47
+ To_Ruby<To_Ruby_T> toRuby_;
48
+ };
49
+ }
50
+
51
+ #endif // Rice__detail__Native_Proc__hpp_
@@ -0,0 +1,133 @@
1
+ #include <algorithm>
2
+ #include <array>
3
+ #include <stdexcept>
4
+ #include <sstream>
5
+ #include <tuple>
6
+
7
+ namespace Rice::detail
8
+ {
9
+ template<typename Proc_T>
10
+ NativeProc<Proc_T>* NativeProc<Proc_T>::define(Proc_T proc)
11
+ {
12
+ MethodInfo* methodInfo = new MethodInfo(detail::function_traits<Proc_T>::arity);
13
+ return new NativeProc_T(std::forward<Proc_T>(proc), methodInfo);
14
+ }
15
+
16
+ template<typename Proc_T>
17
+ VALUE NativeProc<Proc_T>::createRubyProc(Proc_T proc)
18
+ {
19
+ NativeProc_T* nativeProc = NativeProc_T::define(std::forward<Proc_T>(proc));
20
+
21
+ // Create a Ruby proc to wrap it and pass the NativeProc as a callback parameter
22
+ VALUE result = rb_proc_new(NativeProc_T::resolve, (VALUE)nativeProc);
23
+
24
+ // Tie the lifetime of the NativeProc to the Ruby Proc
25
+ VALUE finalizer = rb_proc_new(NativeProc_T::finalizerCallback, (VALUE)nativeProc);
26
+ rb_define_finalizer(result, finalizer);
27
+
28
+ return result;
29
+ }
30
+
31
+ // Ruby calls this method when invoking a proc that was defined as a C++ function
32
+ template<typename Proc_T>
33
+ VALUE NativeProc<Proc_T>::resolve(VALUE yielded_arg, VALUE callback_arg, int argc, const VALUE* argv, VALUE blockarg)
34
+ {
35
+ return cpp_protect([&]
36
+ {
37
+ NativeProc_T * native = (NativeProc_T*)callback_arg;
38
+ return (*native)(argc, argv, Qnil);
39
+ });
40
+ }
41
+
42
+ // Ruby calls this method if an instance of a NativeProc is owned by a Ruby proc. That happens when C++
43
+ // returns a function back to Ruby
44
+ template<typename Proc_T>
45
+ VALUE NativeProc<Proc_T>::finalizerCallback(VALUE yielded_arg, VALUE callback_arg, int argc, const VALUE* argv, VALUE blockarg)
46
+ {
47
+ NativeProc_T* native = (NativeProc_T*)callback_arg;
48
+ delete native;
49
+ return Qnil;
50
+ }
51
+
52
+ template<typename Proc_T>
53
+ NativeProc<Proc_T>::NativeProc(Proc_T proc, MethodInfo* methodInfo) : Native(Native::create_parameters<Arg_Ts>(methodInfo)),
54
+ proc_(proc), methodInfo_(methodInfo)
55
+ {
56
+ }
57
+
58
+ template<typename Proc_T>
59
+ std::string NativeProc<Proc_T>::toString()
60
+ {
61
+ return "Proc";
62
+ }
63
+
64
+ template<typename Proc_T>
65
+ template<std::size_t... I>
66
+ typename NativeProc<Proc_T>::Arg_Ts NativeProc<Proc_T>::getNativeValues(std::vector<std::optional<VALUE>>& values,
67
+ std::index_sequence<I...>& indices)
68
+ {
69
+ /* Loop over each value returned from Ruby and convert it to the appropriate C++ type based
70
+ on the arguments (Arg_Ts) required by the C++ function. Arg_T may have const/volatile while
71
+ the associated From_Ruby<T> template parameter will not. Thus From_Ruby produces non-const values
72
+ which we let the compiler convert to const values as needed. This works except for
73
+ T** -> const T**, see comment in convertToNative method. */
74
+ //return std::forward_as_tuple(this->getNativeValue<std::tuple_element_t<I, Arg_Ts>, I>(values)...);
75
+ return std::forward_as_tuple(
76
+ (dynamic_cast<Parameter<std::tuple_element_t<I, Arg_Ts>>*>(this->parameters_[I].get()))->
77
+ convertToNative(values[I])...);
78
+ }
79
+
80
+ template<typename Proc_T>
81
+ VALUE NativeProc<Proc_T>::invoke(Arg_Ts&& nativeArgs)
82
+ {
83
+ if constexpr (std::is_void_v<Return_T>)
84
+ {
85
+ std::apply(this->proc_, std::forward<Arg_Ts>(nativeArgs));
86
+ return Qnil;
87
+ }
88
+ else
89
+ {
90
+ // Call the native method and get the result
91
+ Return_T nativeResult = std::apply(this->proc_, std::forward<Arg_Ts>(nativeArgs));
92
+
93
+ // Return the result
94
+ return this->toRuby_.convert(std::forward<Return_T>(nativeResult));
95
+ }
96
+ }
97
+
98
+ template<typename Proc_T>
99
+ VALUE NativeProc<Proc_T>::operator()(size_t argc, const VALUE* argv, VALUE self)
100
+ {
101
+ // Get the ruby values and make sure we have the correct number
102
+ std::vector<std::optional<VALUE>> rubyValues = this->getRubyValues(argc, argv, true);
103
+
104
+ auto indices = std::make_index_sequence<std::tuple_size_v<Arg_Ts>>{};
105
+
106
+ // Convert the Ruby values to native values
107
+ Arg_Ts nativeValues = this->getNativeValues(rubyValues, indices);
108
+
109
+ // Now call the native method
110
+ VALUE result = this->invoke(std::forward<Arg_Ts>(nativeValues));
111
+
112
+ return result;
113
+ }
114
+
115
+ template<typename Proc_T>
116
+ inline std::string NativeProc< Proc_T>::name()
117
+ {
118
+ return "proc";
119
+ }
120
+
121
+ template<typename Proc_T>
122
+ inline NativeKind NativeProc< Proc_T>::kind()
123
+ {
124
+ return NativeKind::Proc;
125
+ }
126
+
127
+ template<typename Proc_T>
128
+ inline VALUE NativeProc<Proc_T>::returnKlass()
129
+ {
130
+ TypeMapper<Return_T> typeMapper;
131
+ return typeMapper.rubyKlass();
132
+ }
133
+ }
@@ -25,8 +25,16 @@ namespace Rice::detail
25
25
  class NativeRegistry
26
26
  {
27
27
  public:
28
+ // std::is_copy_constructible returns true for std::vector<std::unique_ptr> - so we need
29
+ // to force the issue
30
+ NativeRegistry() = default;
31
+ NativeRegistry(const NativeRegistry& other) = delete;
32
+ NativeRegistry& operator=(const NativeRegistry& other) = delete;
33
+
28
34
  void add(VALUE klass, ID methodId, std::unique_ptr<Native>& native);
29
35
  void reset(VALUE klass);
36
+
37
+ const std::vector<Native*> lookup(VALUE klass);
30
38
  const std::vector<std::unique_ptr<Native>>& lookup(VALUE klass, ID methodId);
31
39
 
32
40
  private:
@@ -33,6 +33,32 @@ namespace Rice::detail
33
33
  }
34
34
  }
35
35
 
36
+ inline const std::vector<Native*> NativeRegistry::lookup(VALUE klass)
37
+ {
38
+ std::vector<Native*> result;
39
+
40
+ if (rb_type(klass) == T_ICLASS)
41
+ {
42
+ klass = detail::protect(rb_class_of, klass);
43
+ }
44
+
45
+ for (auto& pair : this->natives_)
46
+ {
47
+ const std::pair<VALUE, ID>& key = pair.first;
48
+
49
+ if (klass == key.first)
50
+ {
51
+ const std::vector<std::unique_ptr<Native>>& value = pair.second;
52
+ for (auto& native : value)
53
+ {
54
+ result.push_back(native.get());
55
+ }
56
+ }
57
+ }
58
+
59
+ return result;
60
+ }
61
+
36
62
  inline const std::vector<std::unique_ptr<Native>>& NativeRegistry::lookup(VALUE klass, ID methodId)
37
63
  {
38
64
  if (rb_type(klass) == T_ICLASS)
@@ -0,0 +1,47 @@
1
+ #ifndef Rice__detail__Parameter__hpp_
2
+ #define Rice__detail__Parameter__hpp_
3
+
4
+ #include <optional>
5
+
6
+ namespace Rice::detail
7
+ {
8
+ class ParameterAbstract
9
+ {
10
+ public:
11
+ ParameterAbstract() = default;
12
+ ParameterAbstract(Arg* arg);
13
+ virtual ~ParameterAbstract() = default;
14
+
15
+ ParameterAbstract(ParameterAbstract&& other) = default;
16
+ ParameterAbstract& operator=(ParameterAbstract&& other) = default;
17
+
18
+ virtual Convertible matches(std::optional<VALUE>& valueOpt) = 0;
19
+ virtual std::string cppTypeName() = 0;
20
+ virtual VALUE klass() = 0;
21
+
22
+ public:
23
+ Arg* arg = nullptr;
24
+ };
25
+
26
+ template<typename T>
27
+ class Parameter: public ParameterAbstract
28
+ {
29
+ public:
30
+ using Type = T;
31
+
32
+ Parameter() = default;
33
+ Parameter(Arg* arg);
34
+ Parameter(Parameter&& other) = default;
35
+ Parameter& operator=(Parameter&& other) = default;
36
+
37
+ T convertToNative(std::optional<VALUE>& valueOpt);
38
+ Convertible matches(std::optional<VALUE>& valueOpt) override;
39
+ std::string cppTypeName() override;
40
+ VALUE klass() override;
41
+
42
+ // std::string typeName() override;
43
+ private:
44
+ From_Ruby<remove_cv_recursive_t<T>> fromRuby_;
45
+ };
46
+ }
47
+ #endif // Rice__detail__Parameter__hpp_
@@ -0,0 +1,105 @@
1
+ namespace Rice::detail
2
+ {
3
+ // ----------- ParameterAbstract ----------------
4
+ inline ParameterAbstract::ParameterAbstract(Arg* arg) : arg(arg)
5
+ {
6
+ }
7
+
8
+ // ----------- Parameter ----------------
9
+ template<typename T>
10
+ inline Parameter<T>::Parameter(Arg* arg) : ParameterAbstract(arg), fromRuby_(arg)
11
+ {
12
+ }
13
+
14
+ template<typename T>
15
+ inline Convertible Parameter<T>::matches(std::optional<VALUE>& valueOpt)
16
+ {
17
+ Convertible result = Convertible::None;
18
+
19
+ // Is a VALUE being passed directly to C++ ?
20
+ if (valueOpt.has_value())
21
+ {
22
+ VALUE value = valueOpt.value();
23
+ if (this->arg->isValue())
24
+ {
25
+ result = Convertible::Exact;
26
+ }
27
+ // If index is less than argc then check with FromRuby if the VALUE is convertible
28
+ // to C++.
29
+ else
30
+ {
31
+ result = this->fromRuby_.is_convertible(value);
32
+
33
+ // If this is an exact match check if the const-ness of the value and the parameter match
34
+ if (result == Convertible::Exact && rb_type(value) == RUBY_T_DATA)
35
+ {
36
+ // Check the constness of the Ruby wrapped value and the parameter
37
+ WrapperBase* wrapper = getWrapper(value);
38
+
39
+ // Do not send a const value to a non-const parameter
40
+ if (wrapper->isConst() && !is_const_any_v<T>)
41
+ {
42
+ result = Convertible::None;
43
+ }
44
+ // It is ok to send a non-const value to a const parameter but
45
+ // prefer non-const to non-const by slighly decreasing the convertible value
46
+ else if (!wrapper->isConst() && is_const_any_v<T>)
47
+ {
48
+ result = Convertible::Const;
49
+ }
50
+ }
51
+ }
52
+ }
53
+ // Last check if a default value has been set
54
+ else if (this->arg->hasDefaultValue())
55
+ {
56
+ result = Convertible::Exact;
57
+ }
58
+
59
+ return result;
60
+ }
61
+
62
+ template<typename T>
63
+ inline T Parameter<T>::convertToNative(std::optional<VALUE>& valueOpt)
64
+ {
65
+ /* In general the compiler will convert T to const T, but that does not work for converting
66
+ T** to const T** (see see https://isocpp.org/wiki/faq/const-correctness#constptrptr-conversion)
67
+ which comes up in the OpenCV bindings.
68
+
69
+ An alternative solution is updating From_Ruby#convert to become a templated function that specifies
70
+ the return type. That works but requires a lot more code changes for this one case and is not
71
+ backwards compatible. */
72
+
73
+ if constexpr (is_pointer_pointer_v<T> && !std::is_convertible_v<remove_cv_recursive_t<T>, T>)
74
+ {
75
+ return (T)this->fromRuby_.convert(valueOpt.value());
76
+ }
77
+ else if (valueOpt.has_value())
78
+ {
79
+ return this->fromRuby_.convert(valueOpt.value());
80
+ }
81
+ else if constexpr (std::is_constructible_v<std::remove_cv_t<T>, std::remove_cv_t<std::remove_reference_t<T>>&>)
82
+ {
83
+ if (this->arg->hasDefaultValue())
84
+ {
85
+ return this->arg->template defaultValue<T>();
86
+ }
87
+ }
88
+
89
+ throw std::invalid_argument("Could not convert Rubyy value");
90
+ }
91
+
92
+ template<typename T>
93
+ inline std::string Parameter<T>::cppTypeName()
94
+ {
95
+ detail::TypeMapper<T> typeMapper;
96
+ return typeMapper.simplifiedName();
97
+ }
98
+
99
+ template<typename T>
100
+ inline VALUE Parameter<T>::klass()
101
+ {
102
+ TypeMapper<T> typeMapper;
103
+ return typeMapper.rubyKlass();
104
+ }
105
+ }
data/rice/detail/Proc.ipp CHANGED
@@ -1,15 +1,17 @@
1
1
  namespace Rice::detail
2
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
3
  template<typename Return_T, typename ...Arg_Ts>
7
- struct Type<Return_T(Arg_Ts...)>
4
+ struct Type<Return_T(*)(Arg_Ts...)>
8
5
  {
9
6
  static bool verify()
10
7
  {
11
8
  return true;
12
9
  }
10
+
11
+ static VALUE rubyKlass()
12
+ {
13
+ return rb_cProc;
14
+ }
13
15
  };
14
16
 
15
17
  // Wraps a C++ function as a Ruby proc
@@ -19,17 +21,16 @@ namespace Rice::detail
19
21
  public:
20
22
  using Proc_T = Return_T(*)(Arg_Ts...);
21
23
 
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);
24
+ To_Ruby() = default;
27
25
 
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);
26
+ explicit To_Ruby(Arg* arg)
27
+ {
28
+ }
31
29
 
32
- return result;
30
+ VALUE convert(Proc_T proc)
31
+ {
32
+ // Wrap the C+++ function pointer as a Ruby Proc
33
+ return NativeProc<Proc_T>::createRubyProc(std::forward<Proc_T>(proc));
33
34
  }
34
35
  };
35
36
 
@@ -11,6 +11,7 @@ namespace Rice::detail
11
11
  public:
12
12
  HandlerRegistry handlers;
13
13
  InstanceRegistry instances;
14
+ ModuleRegistry modules;
14
15
  NativeRegistry natives;
15
16
  TypeRegistry types;
16
17
  };
@@ -9,8 +9,6 @@ namespace Rice::detail
9
9
  class RubyType
10
10
  {
11
11
  };
12
-
13
- void define_ruby_types();
14
12
  }
15
13
 
16
14
  #endif // Rice__detail__ruby__type__hpp_
@@ -11,6 +11,7 @@ namespace Rice::detail
11
11
  static inline std::set<ruby_value_type> Castable = { RUBY_T_NIL };
12
12
  static inline std::set<ruby_value_type> Narrowable = { };
13
13
  static inline std::string packTemplate = "not supported";
14
+ static inline std::string name = "bool";
14
15
  };
15
16
 
16
17
  template<>
@@ -24,6 +25,7 @@ namespace Rice::detail
24
25
  static inline std::set<ruby_value_type> Castable = { RUBY_T_STRING };
25
26
  static inline std::set<ruby_value_type> Narrowable = { RUBY_T_FIXNUM };
26
27
  static inline std::string packTemplate = CHAR_MIN < 0 ? "c*" : "C*";
28
+ static inline std::string name = "String";
27
29
  };
28
30
 
29
31
  template<>
@@ -38,6 +40,7 @@ namespace Rice::detail
38
40
  static inline std::set<ruby_value_type> Castable = { RUBY_T_STRING };
39
41
  static inline std::set<ruby_value_type> Narrowable = { RUBY_T_FIXNUM };
40
42
  static inline std::string packTemplate = "c*";
43
+ static inline std::string name = "String";
41
44
  };
42
45
 
43
46
  template<>
@@ -52,6 +55,7 @@ namespace Rice::detail
52
55
  static inline std::set<ruby_value_type> Castable = { RUBY_T_STRING };
53
56
  static inline std::set<ruby_value_type> Narrowable = { RUBY_T_FIXNUM };
54
57
  static inline std::string packTemplate = "C*";
58
+ static inline std::string name = "String";
55
59
  };
56
60
 
57
61
  template<>
@@ -65,6 +69,7 @@ namespace Rice::detail
65
69
  static inline std::set<ruby_value_type> Castable = { };
66
70
  static inline std::set<ruby_value_type> Narrowable = { RUBY_T_FIXNUM };
67
71
  static inline std::string packTemplate = "s*";
72
+ static inline std::string name = "Integer";
68
73
  };
69
74
 
70
75
  template<>
@@ -78,6 +83,7 @@ namespace Rice::detail
78
83
  static inline std::set<ruby_value_type> Castable = { };
79
84
  static inline std::set<ruby_value_type> Narrowable = { RUBY_T_FIXNUM };
80
85
  static inline std::string packTemplate = "S*";
86
+ static inline std::string name = "Integer";
81
87
  };
82
88
 
83
89
  template<>
@@ -93,6 +99,7 @@ namespace Rice::detail
93
99
  // while int can go up to 4 billion
94
100
  static inline std::set<ruby_value_type> Narrowable = { RUBY_T_BIGNUM };
95
101
  static inline std::string packTemplate = "i*";
102
+ static inline std::string name = "Integer";
96
103
  };
97
104
 
98
105
  template<>
@@ -108,6 +115,7 @@ namespace Rice::detail
108
115
  // while int can go up to 4 billion
109
116
  static inline std::set<ruby_value_type> Narrowable = { RUBY_T_BIGNUM };
110
117
  static inline std::string packTemplate = "I*";
118
+ static inline std::string name = "Integer";
111
119
  };
112
120
 
113
121
  template<>
@@ -121,6 +129,7 @@ namespace Rice::detail
121
129
  static inline std::set<ruby_value_type> Castable = { };
122
130
  static inline std::set<ruby_value_type> Narrowable = { RUBY_T_BIGNUM };
123
131
  static inline std::string packTemplate = "l_*";
132
+ static inline std::string name = "Integer";
124
133
  };
125
134
 
126
135
  template<>
@@ -134,6 +143,7 @@ namespace Rice::detail
134
143
  static inline std::set<ruby_value_type> Castable = { };
135
144
  static inline std::set<ruby_value_type> Narrowable = { RUBY_T_BIGNUM};
136
145
  static inline std::string packTemplate = "L_*";
146
+ static inline std::string name = "Integer";
137
147
  };
138
148
 
139
149
  template<>
@@ -147,6 +157,7 @@ namespace Rice::detail
147
157
  static inline std::set<ruby_value_type> Castable = { };
148
158
  static inline std::set<ruby_value_type> Narrowable = { };
149
159
  static inline std::string packTemplate = "q_*";
160
+ static inline std::string name = "Integer";
150
161
  };
151
162
 
152
163
  template<>
@@ -160,6 +171,7 @@ namespace Rice::detail
160
171
  static inline std::set<ruby_value_type> Castable = { };
161
172
  static inline std::set<ruby_value_type> Narrowable = { };
162
173
  static inline std::string packTemplate = "Q_*";
174
+ static inline std::string name = "Integer";
163
175
  };
164
176
 
165
177
  template<>
@@ -173,6 +185,7 @@ namespace Rice::detail
173
185
  static inline std::set<ruby_value_type> Castable = { RUBY_T_FIXNUM };
174
186
  static inline std::set<ruby_value_type> Narrowable = { RUBY_T_FLOAT };
175
187
  static inline std::string packTemplate = "f*";
188
+ static inline std::string name = "Float";
176
189
  };
177
190
 
178
191
  template<>
@@ -186,6 +199,7 @@ namespace Rice::detail
186
199
  static inline std::set<ruby_value_type> Castable = { RUBY_T_FIXNUM, RUBY_T_BIGNUM };
187
200
  static inline std::set<ruby_value_type> Narrowable = { };
188
201
  static inline std::string packTemplate = "d*";
202
+ static inline std::string name = "Float";
189
203
  };
190
204
 
191
205
  template<>
@@ -195,38 +209,6 @@ namespace Rice::detail
195
209
  static inline std::set<ruby_value_type> Exact = { };
196
210
  static inline std::set<ruby_value_type> Castable = { };
197
211
  static inline std::set<ruby_value_type> Narrowable = { };
212
+ static inline std::string name = "void";
198
213
  };
199
- }
200
-
201
- namespace Rice::detail
202
- {
203
- template<typename T>
204
- inline Data_Type<T> define_ruby_type()
205
- {
206
- std::string name = detail::typeName(typeid(T*));
207
- std::string klassName = detail::rubyClassName(name);
208
- Identifier id(klassName);
209
-
210
- Module rb_mRice = define_module("Rice");
211
- return define_class_under<T>(rb_mRice, id);
212
- }
213
-
214
- inline void define_ruby_types()
215
- {
216
- define_ruby_type<bool>();
217
- define_ruby_type<char>();
218
- define_ruby_type<signed char>();
219
- define_ruby_type<unsigned char>();
220
- define_ruby_type<short>();
221
- define_ruby_type<unsigned short>();
222
- define_ruby_type<int>();
223
- define_ruby_type<unsigned int>();
224
- define_ruby_type<long>();
225
- define_ruby_type<unsigned long>();
226
- define_ruby_type<long long>();
227
- define_ruby_type<unsigned long long>();
228
- define_ruby_type<float>();
229
- define_ruby_type<double>();
230
- define_ruby_type<void>();
231
- }
232
214
  }
data/rice/detail/Type.hpp CHANGED
@@ -11,14 +11,50 @@ namespace Rice::detail
11
11
  static bool verify();
12
12
  };
13
13
 
14
- // Return the name of a type
15
- std::string typeName(const std::type_info& typeInfo);
16
- std::string typeName(const std::type_index& typeIndex);
17
- std::string cppClassName(const std::string& typeInfoName);
18
- std::string rubyClassName(const std::string& typeInfoName);
19
- std::string findGroup(std::string& string, size_t start = 0);
20
- void replaceGroup(std::string& string, std::regex regex, std::string replacement);
21
- void replaceAll(std::string& string, std::regex regex, std::string replacement);
14
+ template<typename T>
15
+ struct Type<T&>
16
+ {
17
+ static bool verify();
18
+ };
19
+
20
+ template<typename T>
21
+ struct Type<T&&>
22
+ {
23
+ static bool verify();
24
+ };
25
+
26
+ template<typename T>
27
+ struct Type<T*>
28
+ {
29
+ static bool verify();
30
+ };
31
+
32
+ template<typename T>
33
+ struct Type<T**>
34
+ {
35
+ static bool verify();
36
+ };
37
+
38
+ template<typename T>
39
+ class TypeMapper
40
+ {
41
+ public:
42
+ std::string name();
43
+ std::string name(const std::type_index& typeIndex);
44
+ std::string simplifiedName();
45
+ std::string rubyName();
46
+ VALUE rubyKlass();
47
+
48
+ // public only for testing
49
+ std::string findGroup(std::string& string, size_t start = 0);
50
+ private:
51
+ std::string demangle(char const* mangled_name);
52
+ std::string rubyTypeName();
53
+ void removeGroup(std::string& string, std::regex regex);
54
+ void replaceGroup(std::string& string, std::regex regex, std::string replacement);
55
+ void replaceAll(std::string& string, std::regex regex, std::string replacement);
56
+ void capitalizeHelper(std::string& content, std::regex& regex);
57
+ };
22
58
 
23
59
  template<typename T>
24
60
  void verifyType();