rice 4.7.1 → 4.8.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 (153) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +29 -1
  3. data/CMakeLists.txt +14 -22
  4. data/CMakePresets.json +203 -75
  5. data/FindRuby.cmake +358 -123
  6. data/bin/rice-doc.rb +56 -141
  7. data/include/rice/api.hpp +248 -0
  8. data/include/rice/rice.hpp +2237 -1657
  9. data/include/rice/stl.hpp +346 -443
  10. data/lib/rice/doc/config.rb +70 -0
  11. data/lib/rice/doc/cpp_reference.rb +1 -4
  12. data/lib/rice/doc/mkdocs.rb +58 -20
  13. data/lib/rice/doc/rice.rb +20 -0
  14. data/lib/rice/doc.rb +1 -0
  15. data/lib/rice/make_rice_headers.rb +7 -0
  16. data/lib/rice/native_registry.rb +2 -2
  17. data/lib/rice/rbs.rb +2 -2
  18. data/lib/rice/version.rb +1 -1
  19. data/lib/rubygems_plugin.rb +12 -9
  20. data/rice/Arg.hpp +12 -6
  21. data/rice/Arg.ipp +14 -7
  22. data/rice/Buffer.ipp +44 -40
  23. data/rice/Callback.hpp +1 -1
  24. data/rice/Callback.ipp +2 -7
  25. data/rice/Constructor.hpp +1 -1
  26. data/rice/Constructor.ipp +11 -11
  27. data/rice/Data_Object.ipp +15 -15
  28. data/rice/Data_Type.hpp +9 -10
  29. data/rice/Data_Type.ipp +22 -25
  30. data/rice/Director.hpp +1 -0
  31. data/rice/Enum.ipp +58 -39
  32. data/rice/Exception.hpp +4 -4
  33. data/rice/Exception.ipp +7 -7
  34. data/rice/NoGVL.hpp +13 -0
  35. data/rice/Reference.hpp +56 -0
  36. data/rice/Reference.ipp +96 -0
  37. data/rice/Return.hpp +4 -1
  38. data/rice/Return.ipp +0 -6
  39. data/rice/cpp_api/Array.hpp +41 -4
  40. data/rice/cpp_api/Array.ipp +105 -9
  41. data/rice/cpp_api/Class.hpp +2 -2
  42. data/rice/cpp_api/Class.ipp +4 -4
  43. data/rice/cpp_api/Hash.ipp +7 -4
  44. data/rice/cpp_api/Module.hpp +4 -4
  45. data/rice/cpp_api/Module.ipp +12 -10
  46. data/rice/cpp_api/Object.hpp +4 -4
  47. data/rice/cpp_api/Object.ipp +15 -12
  48. data/rice/cpp_api/String.hpp +2 -2
  49. data/rice/cpp_api/String.ipp +11 -8
  50. data/rice/cpp_api/Symbol.ipp +7 -7
  51. data/rice/cpp_api/shared_methods.hpp +5 -9
  52. data/rice/detail/InstanceRegistry.hpp +0 -2
  53. data/rice/detail/Native.hpp +31 -21
  54. data/rice/detail/Native.ipp +282 -130
  55. data/rice/detail/NativeAttributeGet.hpp +5 -7
  56. data/rice/detail/NativeAttributeGet.ipp +26 -26
  57. data/rice/detail/NativeAttributeSet.hpp +2 -4
  58. data/rice/detail/NativeAttributeSet.ipp +20 -16
  59. data/rice/detail/NativeCallback.hpp +77 -0
  60. data/rice/detail/NativeCallback.ipp +280 -0
  61. data/rice/detail/NativeFunction.hpp +11 -21
  62. data/rice/detail/NativeFunction.ipp +58 -119
  63. data/rice/detail/NativeInvoker.hpp +4 -4
  64. data/rice/detail/NativeInvoker.ipp +7 -7
  65. data/rice/detail/NativeIterator.hpp +2 -4
  66. data/rice/detail/NativeIterator.ipp +18 -14
  67. data/rice/detail/NativeMethod.hpp +10 -20
  68. data/rice/detail/NativeMethod.ipp +54 -114
  69. data/rice/detail/NativeProc.hpp +5 -7
  70. data/rice/detail/NativeProc.ipp +39 -28
  71. data/rice/detail/NativeRegistry.hpp +0 -1
  72. data/rice/detail/Parameter.hpp +15 -8
  73. data/rice/detail/Parameter.ipp +102 -43
  74. data/rice/detail/Proc.ipp +14 -28
  75. data/rice/detail/RubyType.ipp +2 -53
  76. data/rice/detail/Type.hpp +23 -7
  77. data/rice/detail/Type.ipp +73 -93
  78. data/rice/detail/TypeRegistry.ipp +5 -4
  79. data/rice/detail/Wrapper.hpp +1 -1
  80. data/rice/detail/Wrapper.ipp +18 -10
  81. data/rice/detail/from_ruby.hpp +8 -6
  82. data/rice/detail/from_ruby.ipp +306 -173
  83. data/rice/detail/ruby.hpp +23 -0
  84. data/rice/libc/file.hpp +4 -4
  85. data/rice/rice.hpp +6 -8
  86. data/rice/rice_api/Native.ipp +5 -1
  87. data/rice/rice_api/Parameter.ipp +1 -1
  88. data/rice/ruby_mark.hpp +2 -1
  89. data/rice/stl/complex.ipp +12 -8
  90. data/rice/stl/map.ipp +27 -22
  91. data/rice/stl/monostate.ipp +16 -12
  92. data/rice/stl/multimap.hpp +0 -2
  93. data/rice/stl/multimap.ipp +27 -22
  94. data/rice/stl/optional.ipp +27 -11
  95. data/rice/stl/pair.ipp +5 -5
  96. data/rice/stl/reference_wrapper.ipp +5 -4
  97. data/rice/stl/set.ipp +16 -16
  98. data/rice/stl/shared_ptr.hpp +0 -16
  99. data/rice/stl/shared_ptr.ipp +34 -190
  100. data/rice/stl/string.ipp +18 -18
  101. data/rice/stl/string_view.ipp +1 -1
  102. data/rice/stl/tuple.ipp +15 -36
  103. data/rice/stl/unique_ptr.ipp +18 -8
  104. data/rice/stl/unordered_map.ipp +20 -15
  105. data/rice/stl/variant.ipp +37 -21
  106. data/rice/stl/vector.ipp +41 -36
  107. data/rice/traits/function_traits.hpp +19 -19
  108. data/rice/traits/method_traits.hpp +4 -4
  109. data/rice/traits/rice_traits.hpp +162 -39
  110. data/rice.gemspec +1 -3
  111. data/test/test_Array.cpp +261 -3
  112. data/test/test_Attribute.cpp +6 -3
  113. data/test/test_Buffer.cpp +6 -42
  114. data/test/test_Callback.cpp +77 -23
  115. data/test/test_Data_Object.cpp +1 -1
  116. data/test/test_Data_Type.cpp +21 -22
  117. data/test/test_Director.cpp +2 -4
  118. data/test/test_Enum.cpp +34 -5
  119. data/test/test_File.cpp +9 -5
  120. data/test/test_From_Ruby.cpp +4 -3
  121. data/test/test_GVL.cpp +3 -3
  122. data/test/test_Hash.cpp +1 -1
  123. data/test/test_Iterator.cpp +54 -22
  124. data/test/test_Keep_Alive.cpp +1 -1
  125. data/test/test_Keep_Alive_No_Wrapper.cpp +1 -1
  126. data/test/test_Module.cpp +5 -5
  127. data/test/test_Overloads.cpp +345 -48
  128. data/test/test_Proc.cpp +54 -0
  129. data/test/test_Reference.cpp +181 -0
  130. data/test/test_Self.cpp +2 -2
  131. data/test/test_Stl_Set.cpp +6 -6
  132. data/test/test_Stl_SharedPtr.cpp +54 -30
  133. data/test/test_Stl_String_View.cpp +4 -2
  134. data/test/test_Stl_Tuple.cpp +1 -1
  135. data/test/test_Stl_Variant.cpp +6 -14
  136. data/test/test_Stl_Vector.cpp +61 -30
  137. data/test/test_String.cpp +4 -2
  138. data/test/test_Struct.cpp +1 -1
  139. data/test/test_Symbol.cpp +1 -1
  140. data/test/test_To_Ruby.cpp +1 -0
  141. data/test/test_Type.cpp +36 -35
  142. data/test/test_global_functions.cpp +1 -1
  143. data/test/unittest.cpp +1 -1
  144. data/test/unittest.hpp +5 -5
  145. metadata +10 -10
  146. data/rice/Function.hpp +0 -17
  147. data/rice/Function.ipp +0 -13
  148. data/rice/detail/MethodInfo.hpp +0 -48
  149. data/rice/detail/MethodInfo.ipp +0 -99
  150. data/rice/detail/NativeCallbackFFI.hpp +0 -55
  151. data/rice/detail/NativeCallbackFFI.ipp +0 -152
  152. data/rice/detail/NativeCallbackSimple.hpp +0 -30
  153. data/rice/detail/NativeCallbackSimple.ipp +0 -29
@@ -6,13 +6,14 @@
6
6
 
7
7
  namespace Rice::detail
8
8
  {
9
- template<typename Function_T>
10
- void NativeFunction<Function_T>::define(VALUE klass, std::string method_name, Function_T function, MethodInfo* methodInfo)
9
+ template<typename Function_T, bool NoGVL>
10
+ template<typename ...Arg_Ts>
11
+ void NativeFunction<Function_T, NoGVL>::define(VALUE klass, std::string method_name, Function_T function, Arg_Ts&& ...args)
11
12
  {
12
- // Verify return and argument types
13
- Native::verify_type<Return_T>(methodInfo->returnInfo()->isBuffer());
14
- auto indices = std::make_index_sequence<std::tuple_size_v<Arg_Ts>>{};
15
- Native::verify_args<Arg_Ts>(methodInfo, indices);
13
+ // Verify return type
14
+ using Arg_Tuple = std::tuple<Arg_Ts...>;
15
+ constexpr bool isBuffer = tuple_element_index_v<Arg_Tuple, ReturnBuffer> < std::tuple_size_v<Arg_Tuple>;
16
+ Native::verify_type<Return_T, isBuffer>();
16
17
 
17
18
  // Have we defined this method yet in Ruby?
18
19
  Identifier identifier(method_name);
@@ -23,24 +24,29 @@ namespace Rice::detail
23
24
  detail::protect(rb_define_method, klass, method_name.c_str(), (RUBY_METHOD_FUNC)&Native::resolve, -1);
24
25
  }
25
26
 
26
- // Create a NativeFunction instance and save it to the NativeRegistry. There may be multiple
27
- // NativeFunction instances for a specific method because C++ supports method overloading.
28
- NativeFunction_T* nativeFunction = new NativeFunction_T(klass, method_name, std::forward<Function_T>(function), methodInfo);
27
+ // Create function parameters - this will also validate their types
28
+ std::vector<std::unique_ptr<ParameterAbstract>> parameters = Native::create_parameters<Parameter_Ts>(args...);
29
+
30
+ // Create return info
31
+ std::unique_ptr<Return> returnInfo = Native::create_return<Arg_Ts...>(args...);
32
+
33
+ // Create native method
34
+ NativeFunction_T* nativeFunction = new NativeFunction_T(klass, method_name, std::forward<Function_T>(function), std::move(returnInfo), std::move(parameters));
29
35
  std::unique_ptr<Native> native(nativeFunction);
36
+
37
+ // Register the native function
30
38
  detail::Registries::instance.natives.add(klass, identifier.id(), native);
31
39
  }
32
40
 
33
- template<typename Function_T>
34
- NativeFunction<Function_T>::NativeFunction(VALUE klass, std::string method_name, Function_T function, MethodInfo* methodInfo)
35
- : Native(Native::create_parameters<Arg_Ts>(methodInfo)),
36
- klass_(klass), method_name_(method_name), function_(function), methodInfo_(methodInfo),
37
- toRuby_(methodInfo->returnInfo())
41
+ template<typename Function_T, bool NoGVL>
42
+ NativeFunction<Function_T, NoGVL>::NativeFunction(VALUE klass, std::string function_name, Function_T function, std::unique_ptr<Return>&& returnInfo, std::vector<std::unique_ptr<ParameterAbstract>>&& parameters)
43
+ : Native(function_name, std::move(returnInfo), std::move(parameters)),
44
+ klass_(klass), function_(function), toRuby_(returnInfo_.get())
38
45
  {
39
46
  }
40
47
 
41
- template<typename Function_T>
42
- template<std::size_t... I>
43
- std::vector<std::string> NativeFunction<Function_T>::argTypeNames(std::ostringstream& stream, std::index_sequence<I...>& indices)
48
+ template<typename Function_T, bool NoGVL>
49
+ std::vector<std::string> NativeFunction<Function_T, NoGVL>::argTypeNames()
44
50
  {
45
51
  std::vector<std::string> result;
46
52
  for (std::unique_ptr<ParameterAbstract>& parameter : this->parameters_)
@@ -50,19 +56,18 @@ namespace Rice::detail
50
56
  return result;
51
57
  }
52
58
 
53
- template<typename Function_T>
54
- std::string NativeFunction<Function_T>::toString()
59
+ template<typename Function_T, bool NoGVL>
60
+ std::string NativeFunction<Function_T, NoGVL>::toString()
55
61
  {
56
62
  std::ostringstream result;
57
63
 
58
- detail::TypeMapper<Return_T> typeMapper;
59
- result << typeMapper.simplifiedName() << " ";
60
- result << this->method_name_;
64
+ detail::TypeIndexParser typeIndexParser(typeid(Return_T), std::is_fundamental_v<detail::intrinsic_type<Return_T>>);
65
+ result << typeIndexParser.simplifiedName() << " ";
66
+ result << this->name();
61
67
 
62
68
  result << "(";
63
69
 
64
- auto indices = std::make_index_sequence<std::tuple_size_v<Arg_Ts>>{};
65
- std::vector<std::string> argTypeNames = this->argTypeNames(result, indices);
70
+ std::vector<std::string> argTypeNames = this->argTypeNames();
66
71
  for (size_t i = 0; i < argTypeNames.size(); i++)
67
72
  {
68
73
  result << argTypeNames[i];
@@ -73,138 +78,78 @@ namespace Rice::detail
73
78
  return result.str();
74
79
  }
75
80
 
76
- template<typename Function_T>
81
+ template<typename Function_T, bool NoGVL>
77
82
  template<std::size_t... I>
78
- typename NativeFunction<Function_T>::Arg_Ts NativeFunction<Function_T>::getNativeValues(std::vector<std::optional<VALUE>>& values,
79
- std::index_sequence<I...>& indices)
83
+ typename NativeFunction<Function_T, NoGVL>::Parameter_Ts NativeFunction<Function_T, NoGVL>::getNativeValues(std::vector<std::optional<VALUE>>& values,
84
+ std::index_sequence<I...>&)
80
85
  {
81
86
  /* Loop over each value returned from Ruby and convert it to the appropriate C++ type based
82
- on the arguments (Arg_Ts) required by the C++ function. Arg_T may have const/volatile while
87
+ on the arguments (Parameter_Ts) required by the C++ function. Arg_T may have const/volatile while
83
88
  the associated From_Ruby<T> template parameter will not. Thus From_Ruby produces non-const values
84
89
  which we let the compiler convert to const values as needed. This works except for
85
90
  T** -> const T**, see comment in convertToNative method. */
86
- //return std::forward_as_tuple(this->getNativeValue<std::tuple_element_t<I, Arg_Ts>, I>(values)...);
91
+ //return std::forward_as_tuple(this->getNativeValue<std::tuple_element_t<I, Parameter_Ts>, I>(values)...);
87
92
  return std::forward_as_tuple(
88
- (dynamic_cast<Parameter<std::tuple_element_t<I, Arg_Ts>>*>(this->parameters_[I].get()))->
93
+ (dynamic_cast<Parameter<std::tuple_element_t<I, Parameter_Ts>>*>(this->parameters_[I].get()))->
89
94
  convertToNative(values[I])...);
90
95
  }
91
96
 
92
- template<typename Function_T>
93
- VALUE NativeFunction<Function_T>::invoke(Arg_Ts&& nativeArgs)
97
+ template<typename Function_T, bool NoGVL>
98
+ VALUE NativeFunction<Function_T, NoGVL>::invoke(Parameter_Ts&& nativeArgs)
94
99
  {
95
100
  if constexpr (std::is_void_v<Return_T>)
96
101
  {
97
- std::apply(this->function_, std::forward<Arg_Ts>(nativeArgs));
102
+ std::apply(this->function_, std::forward<Parameter_Ts>(nativeArgs));
98
103
  return Qnil;
99
104
  }
100
105
  else
101
106
  {
102
107
  // Call the native method and get the result
103
- Return_T nativeResult = std::apply(this->function_, std::forward<Arg_Ts>(nativeArgs));
108
+ Return_T nativeResult = std::apply(this->function_, std::forward<Parameter_Ts>(nativeArgs));
104
109
 
105
110
  // Return the result
106
111
  return this->toRuby_.convert(nativeResult);
107
112
  }
108
113
  }
109
114
 
110
- template<typename Function_T>
111
- VALUE NativeFunction<Function_T>::invokeNoGVL(Arg_Ts&& nativeArgs)
115
+ template<typename Function_T, bool NoGVL>
116
+ VALUE NativeFunction<Function_T, NoGVL>::invokeNoGVL(Parameter_Ts&& nativeArgs)
112
117
  {
113
118
  if constexpr (std::is_void_v<Return_T>)
114
119
  {
115
- no_gvl(this->function_, std::forward<Arg_Ts>(nativeArgs));
120
+ no_gvl(this->function_, std::forward<Parameter_Ts>(nativeArgs));
116
121
  return Qnil;
117
122
  }
118
123
  else
119
124
  {
120
125
  // Call the native method and get the result
121
- Return_T nativeResult = no_gvl(this->function_, std::forward<Arg_Ts>(nativeArgs));
126
+ Return_T nativeResult = no_gvl(this->function_, std::forward<Parameter_Ts>(nativeArgs));
122
127
 
123
128
  // Return the result
124
129
  return this->toRuby_.convert(nativeResult);
125
130
  }
126
131
  }
127
132
 
128
- template<typename Function_T>
129
- void NativeFunction<Function_T>::noWrapper(const VALUE klass, const std::string& wrapper)
130
- {
131
- std::stringstream message;
132
-
133
- message << "When calling the method `";
134
- message << this->method_name_;
135
- message << "' we could not find the wrapper for the '";
136
- message << rb_obj_classname(klass);
137
- message << "' ";
138
- message << wrapper;
139
- message << " type. You should not use keepAlive() on a Return or Arg that is a builtin Rice type.";
140
-
141
- throw std::runtime_error(message.str());
142
- }
143
-
144
- template<typename Function_T>
145
- void NativeFunction<Function_T>::checkKeepAlive(VALUE self, VALUE returnValue, std::vector<std::optional<VALUE>>& rubyValues)
146
- {
147
- // Self will be Qnil for wrapped procs
148
- if (self == Qnil)
149
- return;
150
-
151
- // selfWrapper will be nullptr if this(self) is a builtin type and not an external(wrapped) type
152
- // it is highly unlikely that keepAlive is used in this case but we check anyway
153
- WrapperBase* selfWrapper = getWrapper(self);
154
-
155
- // Check function arguments
156
- for (const Arg& arg : (*this->methodInfo_))
157
- {
158
- if (arg.isKeepAlive())
159
- {
160
- if (selfWrapper == nullptr)
161
- {
162
- noWrapper(self, "self");
163
- }
164
- selfWrapper->addKeepAlive(rubyValues[arg.position].value());
165
- }
166
- }
167
-
168
- // Check return value
169
- if (this->methodInfo_->returnInfo()->isKeepAlive())
170
- {
171
- if (selfWrapper == nullptr)
172
- {
173
- noWrapper(self, "self");
174
- }
175
-
176
- // returnWrapper will be nullptr if returnValue is a built-in type and not an external(wrapped) type
177
- WrapperBase* returnWrapper = getWrapper(returnValue);
178
- if (returnWrapper == nullptr)
179
- {
180
- noWrapper(returnValue, "return");
181
- }
182
- returnWrapper->addKeepAlive(self);
183
- }
184
- }
185
-
186
- template<typename Function_T>
187
- VALUE NativeFunction<Function_T>::operator()(size_t argc, const VALUE* argv, VALUE self)
133
+ template<typename Function_T, bool NoGVL>
134
+ VALUE NativeFunction<Function_T, NoGVL>::operator()(std::map<std::string, VALUE>& values, VALUE self)
188
135
  {
189
136
  // Get the ruby values and make sure we have the correct number
190
- std::vector<std::optional<VALUE>> rubyValues = this->getRubyValues(argc, argv, true);
137
+ std::vector<std::optional<VALUE>> rubyValues = this->getRubyValues(values, true);
191
138
 
192
- auto indices = std::make_index_sequence<std::tuple_size_v<Arg_Ts>>{};
139
+ auto indices = std::make_index_sequence<std::tuple_size_v<Parameter_Ts>>{};
193
140
 
194
141
  // Convert the Ruby values to native values
195
- Arg_Ts nativeValues = this->getNativeValues(rubyValues, indices);
196
-
197
- bool noGvl = this->methodInfo_->function()->isNoGvl();
142
+ Parameter_Ts nativeValues = this->getNativeValues(rubyValues, indices);
198
143
 
199
144
  VALUE result = Qnil;
200
145
 
201
- if (noGvl)
146
+ if constexpr (NoGVL)
202
147
  {
203
- result = this->invokeNoGVL(std::forward<Arg_Ts>(nativeValues));
148
+ result = this->invokeNoGVL(std::forward<Parameter_Ts>(nativeValues));
204
149
  }
205
150
  else
206
151
  {
207
- result = this->invoke(std::forward<Arg_Ts>(nativeValues));
152
+ result = this->invoke(std::forward<Parameter_Ts>(nativeValues));
208
153
  }
209
154
 
210
155
  // Check if any function arguments or return values need to have their lifetimes tied to the receiver
@@ -213,25 +158,19 @@ namespace Rice::detail
213
158
  return result;
214
159
  }
215
160
 
216
- template<typename Function_T>
217
- inline std::string NativeFunction<Function_T>::name()
218
- {
219
- return this->method_name_;
220
- }
221
-
222
- template<typename Function_T>
223
- inline NativeKind NativeFunction<Function_T>::kind()
161
+ template<typename Function_T, bool NoGVL>
162
+ inline NativeKind NativeFunction<Function_T, NoGVL>::kind()
224
163
  {
225
164
  return NativeKind::Function;
226
165
  }
227
-
228
- template<typename Function_T>
229
- inline VALUE NativeFunction<Function_T>::returnKlass()
166
+ template<typename Function_T, bool NoGVL>
167
+ inline VALUE NativeFunction<Function_T, NoGVL>::returnKlass()
230
168
  {
231
169
  // Check if an array is being returned
232
- if (this->methodInfo_->returnInfo()->isBuffer())
170
+ bool isBuffer = dynamic_cast<ReturnBuffer*>(this->returnInfo_.get()) ? true : false;
171
+ if (isBuffer)
233
172
  {
234
- TypeMapper<Pointer<Return_T>> typeMapper;
173
+ TypeMapper<Pointer<detail::remove_cv_recursive_t<std::remove_pointer_t<Return_T>>>> typeMapper;
235
174
  return typeMapper.rubyKlass();
236
175
  }
237
176
  else
@@ -61,11 +61,11 @@ namespace Rice::detail
61
61
  ResultWrapper<Return_T> resultWrapper;
62
62
  };
63
63
 
64
- template<typename Function_T, typename ...Arg_Ts>
65
- auto protect(Function_T func, Arg_Ts...args);
64
+ template<typename Function_T, typename ...Parameter_Ts>
65
+ auto protect(Function_T func, Parameter_Ts...args);
66
66
 
67
- template<typename Function_T, typename ...Arg_Ts>
68
- typename function_traits<Function_T>::return_type no_gvl(Function_T func, Arg_Ts...args);
67
+ template<typename Function_T, typename ...Parameter_Ts>
68
+ typename function_traits<Function_T>::return_type no_gvl(Function_T func, Parameter_Ts...args);
69
69
 
70
70
  template<typename Function_T, typename Tuple_T>
71
71
  typename function_traits<Function_T>::return_type no_gvl(Function_T func, Tuple_T&& args);
@@ -8,7 +8,7 @@ namespace Rice::detail
8
8
  {
9
9
  return std::move(this->result_.value());
10
10
  }
11
- // std::is_copy_constructible_v<std::vector<std::unique_ptr<T>>>> return true. Sigh.
11
+ // std::is_copy_constructible_v<std::vector<std::unique_ptr<T>>>> returns true. Sigh.
12
12
  else if constexpr (detail::is_std_vector_v<Return_T> && std::is_copy_constructible_v<Return_T>)
13
13
  {
14
14
  if constexpr (!std::is_copy_constructible_v<typename Return_T::value_type>)
@@ -112,11 +112,11 @@ namespace Rice::detail
112
112
 
113
113
  // ------- Helper Methods --------
114
114
  // Create a functor for calling a Ruby function and define some aliases for readability.
115
- template<typename Function_T, typename ...Arg_Ts>
116
- auto protect(Function_T func, Arg_Ts...args)
115
+ template<typename Function_T, typename ...Parameter_Ts>
116
+ auto protect(Function_T func, Parameter_Ts...args)
117
117
  {
118
118
  using Return_T = typename function_traits<Function_T>::return_type;
119
- using Tuple_T = std::tuple<Arg_Ts...>;
119
+ using Tuple_T = std::tuple<Parameter_Ts...>;
120
120
  using Invoker_T = NativeInvoker<Return_T, Function_T, Tuple_T>;
121
121
 
122
122
  Tuple_T argsTuple = std::forward_as_tuple(args...);
@@ -157,10 +157,10 @@ namespace Rice::detail
157
157
  }
158
158
  }
159
159
 
160
- template<typename Function_T, typename ...Arg_Ts>
161
- typename function_traits<Function_T>::return_type no_gvl(Function_T func, Arg_Ts...args)
160
+ template<typename Function_T, typename ...Parameter_Ts>
161
+ typename function_traits<Function_T>::return_type no_gvl(Function_T func, Parameter_Ts...args)
162
162
  {
163
- using Tuple_T = std::tuple<Arg_Ts...>;
163
+ using Tuple_T = std::tuple<Parameter_Ts...>;
164
164
  Tuple_T argsTuple = std::forward_as_tuple(args...);
165
165
  return no_gvl(func, argsTuple);
166
166
  }
@@ -26,11 +26,10 @@ namespace Rice::detail
26
26
  void operator=(const NativeIterator_T&) = delete;
27
27
  void operator=(NativeIterator_T&&) = delete;
28
28
 
29
- Resolved matches(size_t argc, const VALUE* argv, VALUE self) override;
30
- VALUE operator()(size_t argc, const VALUE* argv, VALUE self) override;
29
+ Resolved matches(std::map<std::string, VALUE>& values) override;
30
+ VALUE operator()(std::map<std::string, VALUE>& values, VALUE self) override;
31
31
  std::string toString() override;
32
32
 
33
- std::string name() override;
34
33
  NativeKind kind() override;
35
34
  VALUE returnKlass() override;
36
35
 
@@ -42,7 +41,6 @@ namespace Rice::detail
42
41
 
43
42
  private:
44
43
  VALUE klass_;
45
- std::string method_name_;
46
44
  Iterator_Func_T begin_;
47
45
  Iterator_Func_T end_;
48
46
  };
@@ -21,20 +21,20 @@ namespace Rice::detail
21
21
 
22
22
  template <typename T, typename Iterator_Func_T>
23
23
  inline NativeIterator<T, Iterator_Func_T>::NativeIterator(VALUE klass, std::string method_name, Iterator_Func_T begin, Iterator_Func_T end) :
24
- klass_(klass), method_name_(method_name), begin_(begin), end_(end)
24
+ Native(method_name), klass_(klass), begin_(begin), end_(end)
25
25
  {
26
26
  }
27
27
 
28
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)
29
+ inline Resolved NativeIterator<T, Iterator_Func_T>::matches(std::map<std::string, VALUE>&)
30
30
  {
31
- return Resolved{ Convertible::Exact, 1.0, this };
31
+ return Resolved{ Convertible::Exact, this };
32
32
  }
33
33
 
34
34
  template<typename T, typename Iterator_Func_T>
35
35
  inline VALUE NativeIterator<T, Iterator_Func_T>::createRubyEnumerator(VALUE self)
36
36
  {
37
- auto rb_size_function = [](VALUE recv, VALUE argv, VALUE eobj) -> VALUE
37
+ auto rb_size_function = [](VALUE recv, VALUE, VALUE eobj) -> VALUE
38
38
  {
39
39
  // Since we can't capture VALUE self from above (because then we can't send
40
40
  // this lambda to rb_enumeratorize_with_size), extract it from recv
@@ -61,7 +61,7 @@ namespace Rice::detail
61
61
  });
62
62
  };
63
63
 
64
- Identifier identifier(this->method_name_);
64
+ Identifier identifier(this->name());
65
65
  VALUE enumerator = protect(rb_enumeratorize_with_size, self, identifier.to_sym(), 0, nullptr, rb_size_function);
66
66
 
67
67
  // Hack the enumerator object by storing name_ on the enumerator object so
@@ -72,7 +72,7 @@ namespace Rice::detail
72
72
  }
73
73
 
74
74
  template<typename T, typename Iterator_Func_T>
75
- inline VALUE NativeIterator<T, Iterator_Func_T>::operator()(size_t argc, const VALUE* argv, VALUE self)
75
+ inline VALUE NativeIterator<T, Iterator_Func_T>::operator()(std::map<std::string, VALUE>&, VALUE self)
76
76
  {
77
77
  if (!protect(rb_block_given_p))
78
78
  {
@@ -102,12 +102,6 @@ namespace Rice::detail
102
102
  return "";
103
103
  }
104
104
 
105
- template<typename T, typename Iterator_Func_T>
106
- inline std::string NativeIterator<T, Iterator_Func_T>::name()
107
- {
108
- return this->method_name_;
109
- }
110
-
111
105
  template<typename T, typename Iterator_Func_T>
112
106
  inline NativeKind NativeIterator<T, Iterator_Func_T>::kind()
113
107
  {
@@ -117,7 +111,17 @@ namespace Rice::detail
117
111
  template<typename T, typename Iterator_Func_T>
118
112
  inline VALUE NativeIterator<T, Iterator_Func_T>::returnKlass()
119
113
  {
120
- TypeMapper<Value_T> typeMapper;
121
- return typeMapper.rubyKlass();
114
+ // Check if an array is being returned
115
+ bool isBuffer = dynamic_cast<ReturnBuffer*>(this->returnInfo_.get()) ? true : false;
116
+ if (isBuffer)
117
+ {
118
+ TypeMapper<Pointer<detail::remove_cv_recursive_t<std::remove_pointer_t<Value_T>>>> typeMapper;
119
+ return typeMapper.rubyKlass();
120
+ }
121
+ else
122
+ {
123
+ TypeMapper<Value_T> typeMapper;
124
+ return typeMapper.rubyKlass();
125
+ }
122
126
  }
123
127
  }
@@ -35,61 +35,51 @@ namespace Rice::detail
35
35
  * calling them methods (self) or functions (no self).
36
36
  */
37
37
 
38
- template<typename Class_T, typename Method_T>
38
+ template<typename Class_T, typename Method_T, bool NoGVL>
39
39
  class NativeMethod: Native
40
40
  {
41
41
  public:
42
- using NativeMethod_T = NativeMethod<Class_T, Method_T>;
42
+ using NativeMethod_T = NativeMethod<Class_T, Method_T, NoGVL>;
43
43
 
44
44
  // We remove const to avoid an explosion of To_Ruby specializations and Ruby doesn't
45
45
  // have the concept of constants anyways
46
46
  using Return_T = typename method_traits<Method_T>::Return_T;
47
47
  using Receiver_T = typename method_traits<Method_T>::Class_T;
48
- using Arg_Ts = typename method_traits<Method_T>::Arg_Ts;
49
- using Apply_Args_T = typename tuple_unshift<Receiver_T, Arg_Ts>::type;
48
+ using Parameter_Ts = typename method_traits<Method_T>::Parameter_Ts;
49
+ using Apply_Args_T = typename tuple_unshift<Receiver_T, Parameter_Ts>::type;
50
50
 
51
51
  using To_Ruby_T = remove_cv_recursive_t<Return_T>;
52
52
 
53
53
  // Register method with Ruby
54
- static void define(VALUE klass, std::string method_name, Method_T method, MethodInfo* methodInfo);
54
+ template <typename ...Arg_Ts>
55
+ static void define(VALUE klass, std::string method_name, Method_T method, Arg_Ts&& ...args);
55
56
 
56
57
  public:
57
- NativeMethod(VALUE klass, std::string method_name, Method_T method, MethodInfo* methodInfo);
58
+ NativeMethod(VALUE klass, std::string method_name, Method_T method, std::unique_ptr<Return>&& returnInfo, std::vector<std::unique_ptr<ParameterAbstract>>&& parameters);
58
59
 
59
- VALUE operator()(size_t argc, const VALUE* argv, VALUE self) override;
60
+ VALUE operator()(std::map<std::string, VALUE>& values, VALUE self) override;
60
61
  std::string toString() override;
61
62
 
62
- std::string name() override;
63
63
  NativeKind kind() override;
64
64
  VALUE returnKlass() override;
65
65
 
66
66
  private:
67
-
68
- template<std::size_t...I>
69
- std::vector<std::string> argTypeNames(std::ostringstream& stream, std::index_sequence<I...>& indices);
67
+ std::vector<std::string> argTypeNames();
70
68
 
71
69
  // Convert Ruby values to C++ values
72
70
  template<typename std::size_t...I>
73
- Apply_Args_T getNativeValues(VALUE self, std::vector<std::optional<VALUE>>& values, std::index_sequence<I...>& indices);
71
+ Apply_Args_T getNativeValues(VALUE self, std::vector<std::optional<VALUE>>& values, const std::index_sequence<I...>& indices);
74
72
 
75
73
  // Figure out what self is
76
74
  Receiver_T getReceiver(VALUE self);
77
75
 
78
- // Throw an exception when wrapper cannot be extracted
79
- [[noreturn]] void noWrapper(const VALUE klass, const std::string& wrapper);
80
-
81
- // Do we need to keep alive any arguments?
82
- void checkKeepAlive(VALUE self, VALUE returnValue, std::vector<std::optional<VALUE>>& rubyValues);
83
-
84
76
  // Call the underlying C++ method
85
77
  VALUE invoke(VALUE self, Apply_Args_T&& nativeArgs);
86
78
  VALUE invokeNoGVL(VALUE self, Apply_Args_T&& nativeArgs);
87
79
 
88
80
  private:
89
81
  VALUE klass_;
90
- std::string method_name_;
91
82
  Method_T method_;
92
- std::unique_ptr<MethodInfo> methodInfo_;
93
83
  To_Ruby<To_Ruby_T> toRuby_;
94
84
  };
95
85
  }