rice 4.6.1 → 4.7.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 (185) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +31 -0
  3. data/CMakeLists.txt +0 -4
  4. data/Rakefile +2 -8
  5. data/bin/rice-doc.rb +212 -0
  6. data/bin/rice-rbs.rb +93 -0
  7. data/include/rice/rice.hpp +4972 -4015
  8. data/include/rice/stl.hpp +822 -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 +101 -82
  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 +2 -2
  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 +34 -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 -2
  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 +27 -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 +5 -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 +11 -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 +0 -55
  138. data/test/test_Data_Type.cpp +19 -30
  139. data/test/test_Enum.cpp +4 -46
  140. data/test/test_From_Ruby.cpp +88 -81
  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 +3 -3
  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_Tuple.cpp +1 -1
  152. data/test/test_Stl_UniquePtr.cpp +8 -0
  153. data/test/test_Stl_Unordered_Map.cpp +9 -9
  154. data/test/test_Stl_Variant.cpp +9 -3
  155. data/test/test_Stl_Vector.cpp +118 -13
  156. data/test/test_To_Ruby.cpp +35 -28
  157. data/test/test_Type.cpp +256 -53
  158. data/test/unittest.hpp +35 -0
  159. metadata +66 -34
  160. data/rice/Init.hpp +0 -8
  161. data/rice/Init.ipp +0 -8
  162. data/rice/detail/RubyFunction.hpp +0 -31
  163. data/rice/detail/RubyFunction.ipp +0 -77
  164. data/sample/callbacks/extconf.rb +0 -5
  165. data/sample/callbacks/sample_callbacks.cpp +0 -35
  166. data/sample/callbacks/test.rb +0 -28
  167. data/sample/enum/extconf.rb +0 -5
  168. data/sample/enum/sample_enum.cpp +0 -40
  169. data/sample/enum/test.rb +0 -8
  170. data/sample/inheritance/animals.cpp +0 -82
  171. data/sample/inheritance/extconf.rb +0 -5
  172. data/sample/inheritance/test.rb +0 -7
  173. data/sample/map/extconf.rb +0 -5
  174. data/sample/map/map.cpp +0 -73
  175. data/sample/map/test.rb +0 -7
  176. data/test/ext/t1/Foo.hpp +0 -10
  177. data/test/ext/t1/extconf.rb +0 -4
  178. data/test/ext/t1/t1.cpp +0 -13
  179. data/test/ext/t2/extconf.rb +0 -4
  180. data/test/ext/t2/t2.cpp +0 -11
  181. data/test/ruby/test_callbacks_sample.rb +0 -28
  182. data/test/ruby/test_multiple_extensions.rb +0 -18
  183. data/test/ruby/test_multiple_extensions_same_class.rb +0 -14
  184. data/test/ruby/test_multiple_extensions_with_inheritance.rb +0 -20
  185. /data/test/{test_Stl_Type.cpp → test_Stl_Type_Info.cpp} +0 -0
@@ -29,18 +29,20 @@ namespace Rice
29
29
  Arg* arg(std::string name);
30
30
 
31
31
  int argCount();
32
+ Return* returnInfo();
33
+ Function* function();
32
34
 
33
35
  // Iterator support
34
36
  std::vector<Arg>::iterator begin();
35
37
  std::vector<Arg>::iterator end();
36
38
 
37
- Return returnInfo;
38
-
39
39
  private:
40
40
  template <typename Arg_T>
41
41
  void processArg(const Arg_T& arg);
42
42
 
43
43
  std::vector<Arg> args_;
44
+ Return returnInfo_;
45
+ Function function_;
44
46
  };
45
47
  }
46
48
  #endif // Rice__MethodInfo__hpp_
@@ -25,16 +25,22 @@ namespace Rice
25
25
  template <typename Arg_T>
26
26
  inline void MethodInfo::processArg(const Arg_T& arg)
27
27
  {
28
- static_assert(std::is_same_v<Arg_T, Return> || std::is_same_v<Arg_T, Arg>, "Unknown argument type");
29
-
30
28
  if constexpr (std::is_same_v<Arg_T, Return>)
31
29
  {
32
- this->returnInfo = arg;
30
+ this->returnInfo_ = arg;
31
+ }
32
+ else if constexpr (std::is_same_v<Arg_T, Function>)
33
+ {
34
+ this->function_ = arg;
33
35
  }
34
36
  else if constexpr (std::is_same_v<Arg_T, Arg>)
35
37
  {
36
38
  this->addArg(arg);
37
39
  }
40
+ else
41
+ {
42
+ static_assert(true, "Unknown argument type");
43
+ }
38
44
  }
39
45
 
40
46
  inline void MethodInfo::addArg(const Arg& arg)
@@ -71,6 +77,16 @@ namespace Rice
71
77
  return nullptr;
72
78
  }
73
79
 
80
+ inline Return* MethodInfo::returnInfo()
81
+ {
82
+ return &this->returnInfo_;
83
+ }
84
+
85
+ inline Function* MethodInfo::function()
86
+ {
87
+ return &this->function_;
88
+ }
89
+
74
90
  inline std::vector<Arg>::iterator MethodInfo::begin()
75
91
  {
76
92
  return this->args_.begin();
@@ -0,0 +1,18 @@
1
+ #ifndef Rice__ModuleRegistry__hpp_
2
+ #define Rice__ModuleRegistry__hpp_
3
+
4
+ namespace Rice::detail
5
+ {
6
+ class ModuleRegistry
7
+ {
8
+ public:
9
+ void add(VALUE module);
10
+ // API for access from Ruby
11
+ VALUE modules();
12
+
13
+ private:
14
+ std::set<VALUE> modules_{};
15
+ };
16
+ }
17
+
18
+ #endif // Rice__ModuleRegistry__hpp_
@@ -0,0 +1,25 @@
1
+ #include <iostream>
2
+ #include <stdexcept>
3
+ #include <sstream>
4
+ #include <typeindex>
5
+
6
+
7
+ namespace Rice::detail
8
+ {
9
+ inline void ModuleRegistry::add(VALUE module)
10
+ {
11
+ this->modules_.insert(module);
12
+ }
13
+
14
+ inline VALUE ModuleRegistry::modules()
15
+ {
16
+ Array result;
17
+
18
+ for (const VALUE& value : this->modules_)
19
+ {
20
+ Module module(value);
21
+ result.push(module, false);
22
+ }
23
+ return result;
24
+ }
25
+ }
@@ -16,17 +16,60 @@ namespace Rice::detail
16
16
  Native* native;
17
17
  };
18
18
 
19
+ enum class NativeKind
20
+ {
21
+ Function,
22
+ Method,
23
+ Iterator,
24
+ AttributeReader,
25
+ AttributeWriter,
26
+ Proc
27
+ };
28
+
19
29
  class Native
20
30
  {
21
31
  public:
22
32
  static VALUE resolve(int argc, VALUE* argv, VALUE self);
23
33
  public:
34
+ Native() = default;
35
+ Native(std::vector<std::unique_ptr<ParameterAbstract>>&& parameters);
24
36
  virtual ~Native() = default;
25
- VALUE call(int argc, VALUE* argv, VALUE self);
26
37
 
27
- virtual Resolved matches(size_t argc, const VALUE* argv, VALUE self) = 0;
38
+ Native(const Native&) = delete;
39
+ Native(Native&&) = delete;
40
+ void operator=(const Native&) = delete;
41
+ void operator=(Native&&) = delete;
42
+
43
+ virtual Resolved matches(size_t argc, const VALUE* argv, VALUE self);
28
44
  virtual VALUE operator()(size_t argc, const VALUE* argv, VALUE self) = 0;
29
45
  virtual std::string toString() = 0;
46
+
47
+ // Ruby API access
48
+ virtual std::string name() = 0;
49
+ virtual NativeKind kind() = 0;
50
+ virtual VALUE returnKlass() = 0;
51
+ std::vector<const ParameterAbstract*> parameters();
52
+
53
+ protected:
54
+ template<typename T>
55
+ static void verify_type(bool isBuffer);
56
+
57
+ template<typename Tuple_T, std::size_t ...Indices>
58
+ static void verify_args(MethodInfo* methodInfo, std::index_sequence<Indices...> indices);
59
+
60
+ std::vector<std::optional<VALUE>> getRubyValues(size_t argc, const VALUE* argv, bool validate);
61
+ ParameterAbstract* getParameterByName(std::string name);
62
+ Convertible matchParameters(std::vector<std::optional<VALUE>>& values);
63
+
64
+ template<typename Tuple_T>
65
+ static std::vector<std::unique_ptr<ParameterAbstract>> create_parameters(MethodInfo* methodInfo);
66
+
67
+ template<typename Tuple_T, std::size_t ...Indices>
68
+ static inline void create_parameters_impl(std::vector<std::unique_ptr<ParameterAbstract>>& parameters, MethodInfo* methodInfo, std::index_sequence<Indices...> indices);
69
+
70
+ protected:
71
+ std::vector<std::unique_ptr<ParameterAbstract>> parameters_;
72
+
30
73
  };
31
74
  }
32
75
 
@@ -79,7 +79,7 @@ namespace Rice::detail
79
79
  else if (natives.size() == 0)
80
80
  {
81
81
  Identifier identifier(methodId);
82
- rb_raise(rb_eArgError, "Could not find method call for %s#%s", rb_class2name(klass), identifier.c_str());
82
+ rb_enc_raise(rb_utf8_encoding(), rb_eArgError, "Could not find method call for %s#%s", rb_class2name(klass), identifier.c_str());
83
83
  }
84
84
  else
85
85
  {
@@ -145,7 +145,7 @@ namespace Rice::detail
145
145
  message << "\n " << resolve.native->toString();
146
146
  }
147
147
 
148
- rb_raise(rb_eArgError, message.str().c_str(), rb_class2name(klass), identifier.c_str(), natives.size());
148
+ rb_enc_raise(rb_utf8_encoding(), rb_eArgError, message.str().c_str(), rb_class2name(klass), identifier.c_str(), natives.size());
149
149
  }
150
150
  }
151
151
  }
@@ -154,4 +154,198 @@ namespace Rice::detail
154
154
  return (*native)(argc, argv, self);
155
155
  });
156
156
  }
157
+
158
+ inline Native::Native(std::vector<std::unique_ptr<ParameterAbstract>>&& parameters) : parameters_(std::move(parameters))
159
+ {
160
+ }
161
+
162
+ inline ParameterAbstract* Native::getParameterByName(std::string name)
163
+ {
164
+ for (std::unique_ptr<ParameterAbstract>& parameter : this->parameters_)
165
+ {
166
+ if (parameter->arg->name == name)
167
+ {
168
+ return parameter.get();
169
+ }
170
+ }
171
+
172
+ return nullptr;
173
+ }
174
+
175
+ // ----------- Helpers ----------------
176
+ template<typename T>
177
+ inline void Native::verify_type(bool isBuffer)
178
+ {
179
+ using Base_T = std::remove_pointer_t<remove_cv_recursive_t<T>>;
180
+
181
+ detail::verifyType<T>();
182
+
183
+ if constexpr (std::is_pointer_v<T> && std::is_fundamental_v<std::remove_pointer_t<T>>)
184
+ {
185
+ Type<Pointer<std::remove_pointer_t<T>>>::verify();
186
+ Type<Buffer<std::remove_pointer_t<T>>>::verify();
187
+ }
188
+ if constexpr (std::is_array_v<T>)
189
+ {
190
+ Type<Pointer<std::remove_extent_t<remove_cv_recursive_t<T>>>>::verify();
191
+ Type<Buffer<std::remove_extent_t<remove_cv_recursive_t<T>>>>::verify();
192
+ }
193
+ else if (isBuffer)
194
+ {
195
+ if constexpr (std::is_pointer_v<T> && !std::is_function_v<Base_T> && !std::is_abstract_v<Base_T>)
196
+ {
197
+ Type<Pointer<Base_T>>::verify();
198
+ Type<Buffer<Base_T>>::verify();
199
+ }
200
+ else
201
+ {
202
+ static_assert(true, "Only pointer types can be marked as buffers");
203
+ }
204
+ }
205
+ }
206
+
207
+ template<typename Tuple_T, std::size_t ...Indices>
208
+ inline void Native::verify_args(MethodInfo* methodInfo, std::index_sequence<Indices...> indices)
209
+ {
210
+ (Native::verify_type<std::tuple_element_t<Indices, Tuple_T>>(methodInfo->arg(Indices)->isBuffer()), ...);
211
+ }
212
+
213
+ template<typename Tuple_T, std::size_t ...Indices>
214
+ inline void Native::create_parameters_impl(std::vector<std::unique_ptr<ParameterAbstract>>& parameters, MethodInfo* methodInfo, std::index_sequence<Indices...> indices)
215
+ {
216
+ (parameters.push_back(std::move(std::make_unique<Parameter<std::tuple_element_t<Indices, Tuple_T>>>(methodInfo->arg(Indices)))), ...);
217
+ }
218
+
219
+ template<typename Tuple_T>
220
+ inline std::vector<std::unique_ptr<ParameterAbstract>> Native::create_parameters(MethodInfo* methodInfo)
221
+ {
222
+ std::vector<std::unique_ptr<ParameterAbstract>> result;
223
+ auto indices = std::make_index_sequence<std::tuple_size_v<Tuple_T>>{};
224
+ Native::create_parameters_impl<Tuple_T>(result, methodInfo, indices);
225
+ return result;
226
+ }
227
+
228
+ inline std::vector<std::optional<VALUE>> Native::getRubyValues(size_t argc, const VALUE* argv, bool validate)
229
+ {
230
+ #undef max
231
+ int size = std::max(this->parameters_.size(), argc);
232
+ std::vector<std::optional<VALUE>> result(size);
233
+
234
+ // Keyword handling
235
+ if (rb_keyword_given_p())
236
+ {
237
+ // Keywords are stored in the last element in a hash
238
+ int actualArgc = argc - 1;
239
+
240
+ VALUE value = argv[actualArgc];
241
+ Hash keywords(value);
242
+
243
+ // Copy over leading non-keyword arguments
244
+ for (int i = 0; i < actualArgc; i++)
245
+ {
246
+ result[i] = argv[i];
247
+ }
248
+
249
+ // Copy over keyword arguments
250
+ for (auto pair : keywords)
251
+ {
252
+ Symbol key(pair.first);
253
+ ParameterAbstract* parameter = this->getParameterByName(key.str());
254
+ if (!parameter)
255
+ {
256
+ throw std::invalid_argument("Unknown keyword: " + key.str());
257
+ }
258
+
259
+ const Arg* arg = parameter->arg;
260
+
261
+ result[arg->position] = pair.second.value();
262
+ }
263
+ }
264
+ else
265
+ {
266
+ std::copy(argv, argv + argc, result.begin());
267
+ }
268
+
269
+ // Block handling. If we find a block and the last parameter is missing then
270
+ // set it to the block
271
+ if (rb_block_given_p() && result.size() > 0 && !result.back().has_value())
272
+ {
273
+ VALUE proc = rb_block_proc();
274
+ result.back() = proc;
275
+ }
276
+
277
+ if (validate)
278
+ {
279
+ // Protect against user sending too many arguments
280
+ if (argc > this->parameters_.size())
281
+ {
282
+ std::string message = "wrong number of arguments (given " +
283
+ std::to_string(argc) + ", expected " + std::to_string(this->parameters_.size()) + ")";
284
+ throw std::invalid_argument(message);
285
+ }
286
+
287
+ for (size_t i = 0; i < result.size(); i++)
288
+ {
289
+ std::optional<VALUE> value = result[i];
290
+ ParameterAbstract* parameter = this->parameters_[i].get();
291
+
292
+ if (!parameter->arg->hasDefaultValue() && !value.has_value())
293
+ {
294
+ std::string message;
295
+ message = "Missing argument. Name: " + parameter->arg->name + ". Index: " + std::to_string(parameter->arg->position) + ".";
296
+ throw std::invalid_argument(message);
297
+ }
298
+ }
299
+ }
300
+
301
+ return result;
302
+ }
303
+
304
+ inline Convertible Native::matchParameters(std::vector<std::optional<VALUE>>& values)
305
+ {
306
+ Convertible result = Convertible::Exact;
307
+ for (size_t i = 0; i < this->parameters_.size(); i++)
308
+ {
309
+ ParameterAbstract* parameter = this->parameters_[i].get();
310
+ std::optional<VALUE>& value = values[i];
311
+ result = result & parameter->matches(value);
312
+ }
313
+ return result;
314
+ }
315
+
316
+ inline Resolved Native::matches(size_t argc, const VALUE* argv, VALUE self)
317
+ {
318
+ // Return false if Ruby provided more arguments than the C++ method takes
319
+ if (argc > this->parameters_.size())
320
+ return Resolved{ Convertible::None, 0, this };
321
+
322
+ Resolved result{ Convertible::Exact, 1, this };
323
+
324
+ std::vector<std::optional<VALUE>> rubyValues = this->getRubyValues(argc, argv, false);
325
+ result.convertible = this->matchParameters(rubyValues);
326
+
327
+ if (this->parameters_.size() > 0)
328
+ {
329
+ int providedValues = std::count_if(rubyValues.begin(), rubyValues.end(), [](std::optional<VALUE>& value)
330
+ {
331
+ return value.has_value();
332
+ });
333
+
334
+ result.parameterMatch = providedValues / (double)this->parameters_.size();
335
+ }
336
+ return result;
337
+ }
338
+
339
+ inline std::vector<const ParameterAbstract*> Native::parameters()
340
+ {
341
+ std::vector<const ParameterAbstract*> result;
342
+
343
+ std::transform(this->parameters_.begin(), this->parameters_.end(), std::back_inserter(result),
344
+ [](std::unique_ptr<ParameterAbstract>& parameter) -> ParameterAbstract*
345
+ {
346
+ return parameter.get();
347
+ });
348
+
349
+ return result;
350
+ }
157
351
  }
@@ -18,13 +18,13 @@ namespace Rice
18
18
  public:
19
19
  using NativeAttribute_T = NativeAttributeGet<Attribute_T>;
20
20
 
21
- using T = typename attribute_traits<Attribute_T>::attr_type;
21
+ using Attr_T = typename attribute_traits<Attribute_T>::attr_type;
22
22
  using Receiver_T = typename attribute_traits<Attribute_T>::class_type;
23
- using To_Ruby_T = remove_cv_recursive_t<T>;
23
+ using To_Ruby_T = remove_cv_recursive_t<Attr_T>;
24
24
 
25
25
  public:
26
26
  // Register attribute getter with Ruby
27
- static void define(VALUE klass, std::string name, Attribute_T attribute);
27
+ static void define(VALUE klass, std::string name, Attribute_T attribute, Return returnInfo);
28
28
 
29
29
  public:
30
30
  // Disallow creating/copying/moving
@@ -38,13 +38,18 @@ namespace Rice
38
38
  VALUE operator()(size_t argc, const VALUE* argv, VALUE self) override;
39
39
  std::string toString() override;
40
40
 
41
+ std::string name() override;
42
+ NativeKind kind() override;
43
+ VALUE returnKlass() override;
44
+
41
45
  protected:
42
- NativeAttributeGet(VALUE klass, std::string name, Attribute_T attr);
46
+ NativeAttributeGet(VALUE klass, std::string name, Attribute_T attr, Return returnInfo);
43
47
 
44
48
  private:
45
49
  VALUE klass_;
46
50
  std::string name_;
47
51
  Attribute_T attribute_;
52
+ Return return_;
48
53
  };
49
54
  } // detail
50
55
  } // Rice
@@ -1,14 +1,16 @@
1
1
  #include <array>
2
2
  #include <algorithm>
3
3
 
4
-
5
4
  namespace Rice::detail
6
5
  {
7
6
  template<typename Attribute_T>
8
- void NativeAttributeGet<Attribute_T>::define(VALUE klass, std::string name, Attribute_T attribute)
7
+ void NativeAttributeGet<Attribute_T>::define(VALUE klass, std::string name, Attribute_T attribute, Return returnInfo)
9
8
  {
9
+ // Verify attribute type
10
+ Native::verify_type<Attr_T>(returnInfo.isBuffer());
11
+
10
12
  // Create a NativeAttributeGet that Ruby will call to read/write C++ variables
11
- NativeAttribute_T* nativeAttribute = new NativeAttribute_T(klass, name, std::forward<Attribute_T>(attribute));
13
+ NativeAttribute_T* nativeAttribute = new NativeAttribute_T(klass, name, std::forward<Attribute_T>(attribute), returnInfo);
12
14
  std::unique_ptr<Native> native(nativeAttribute);
13
15
 
14
16
  detail::protect(rb_define_method, klass, name.c_str(), (RUBY_METHOD_FUNC)&Native::resolve, -1);
@@ -30,8 +32,8 @@ namespace Rice::detail
30
32
  }
31
33
 
32
34
  template<typename Attribute_T>
33
- NativeAttributeGet<Attribute_T>::NativeAttributeGet(VALUE klass, std::string name, Attribute_T attribute)
34
- : klass_(klass), name_(name), attribute_(attribute)
35
+ NativeAttributeGet<Attribute_T>::NativeAttributeGet(VALUE klass, std::string name, Attribute_T attribute, Return returnInfo)
36
+ : klass_(klass), name_(name), attribute_(attribute), return_(returnInfo)
35
37
  {
36
38
  }
37
39
 
@@ -42,21 +44,45 @@ namespace Rice::detail
42
44
  {
43
45
  Receiver_T* nativeSelf = From_Ruby<Receiver_T*>().convert(self);
44
46
 
45
- if constexpr (std::is_fundamental_v<detail::intrinsic_type<To_Ruby_T>> ||
46
- (std::is_array_v<To_Ruby_T> && std::is_fundamental_v<std::remove_extent_t<To_Ruby_T>>))
47
+ if constexpr (std::is_fundamental_v<detail::intrinsic_type<To_Ruby_T>>)
47
48
  {
48
- return To_Ruby<To_Ruby_T>().convert(nativeSelf->*attribute_);
49
+ return To_Ruby<To_Ruby_T>(&this->return_).convert(nativeSelf->*attribute_);
50
+ }
51
+ else if constexpr (std::is_array_v<To_Ruby_T>)
52
+ {
53
+ return To_Ruby<To_Ruby_T>(&this->return_).convert(nativeSelf->*attribute_);
54
+ }
55
+ else if constexpr (std::is_pointer_v<To_Ruby_T>)
56
+ {
57
+ return To_Ruby<To_Ruby_T>(&this->return_).convert(nativeSelf->*attribute_);
49
58
  }
50
59
  else
51
60
  {
52
61
  // If the attribute is an object return a reference to avoid a copy (and avoid issues with
53
62
  // attributes that are not assignable, copy constructible or move constructible)
54
- return To_Ruby<To_Ruby_T&>().convert(nativeSelf->*attribute_);
63
+ return To_Ruby<To_Ruby_T&>(&this->return_).convert(nativeSelf->*attribute_);
55
64
  }
56
65
  }
57
66
  else
58
67
  {
59
- return To_Ruby<To_Ruby_T>().convert(*attribute_);
68
+ if constexpr (std::is_fundamental_v<detail::intrinsic_type<To_Ruby_T>>)
69
+ {
70
+ return To_Ruby<To_Ruby_T>(&this->return_).convert(*attribute_);
71
+ }
72
+ else if constexpr (std::is_array_v<To_Ruby_T>)
73
+ {
74
+ return To_Ruby<To_Ruby_T>(&this->return_).convert(*attribute_);
75
+ }
76
+ else if constexpr (std::is_pointer_v<To_Ruby_T>)
77
+ {
78
+ return To_Ruby<To_Ruby_T>(&this->return_).convert(*attribute_);
79
+ }
80
+ else
81
+ {
82
+ // If the attribute is an object return a reference to avoid a copy (and avoid issues with
83
+ // attributes that are not assignable, copy constructible or move constructible)
84
+ return To_Ruby<To_Ruby_T&>(&this->return_).convert(*attribute_);
85
+ }
60
86
  }
61
87
  }
62
88
 
@@ -65,4 +91,32 @@ namespace Rice::detail
65
91
  {
66
92
  return "";
67
93
  }
68
- } // Rice
94
+
95
+ template<typename Attribute_T>
96
+ inline std::string NativeAttributeGet<Attribute_T>::name()
97
+ {
98
+ return this->name_;
99
+ }
100
+
101
+ template<typename Attribute_T>
102
+ inline NativeKind NativeAttributeGet<Attribute_T>::kind()
103
+ {
104
+ return NativeKind::AttributeReader;
105
+ }
106
+
107
+ template<typename Attribute_T>
108
+ inline VALUE NativeAttributeGet<Attribute_T>::returnKlass()
109
+ {
110
+ // Check if an array is being returned
111
+ if (this->return_.isBuffer())
112
+ {
113
+ TypeMapper<Pointer<Attr_T>> typeMapper;
114
+ return typeMapper.rubyKlass();
115
+ }
116
+ else
117
+ {
118
+ TypeMapper<Attr_T> typeMapper;
119
+ return typeMapper.rubyKlass();
120
+ }
121
+ }
122
+ }
@@ -30,6 +30,10 @@ namespace Rice
30
30
  VALUE operator()(size_t argc, const VALUE* argv, VALUE self) override;
31
31
  std::string toString() override;
32
32
 
33
+ std::string name() override;
34
+ NativeKind kind() override;
35
+ VALUE returnKlass() override;
36
+
33
37
  protected:
34
38
  NativeAttributeSet(VALUE klass, std::string name, Attribute_T attr);
35
39
 
@@ -52,7 +52,16 @@ namespace Rice::detail
52
52
  if constexpr (!std::is_null_pointer_v<Receiver_T>)
53
53
  {
54
54
  Receiver_T* nativeSelf = From_Ruby<Receiver_T*>().convert(self);
55
- nativeSelf->*attribute_ = From_Ruby<T_Unqualified>().convert(value);
55
+
56
+ // Deal with pointers to pointes, see Parameter::convertToNative commment
57
+ if constexpr (is_pointer_pointer_v<Attr_T> && !std::is_convertible_v<remove_cv_recursive_t<Attr_T>, Attr_T>)
58
+ {
59
+ nativeSelf->*attribute_ = (Attr_T)From_Ruby<T_Unqualified>().convert(value);
60
+ }
61
+ else
62
+ {
63
+ nativeSelf->*attribute_ = From_Ruby<T_Unqualified>().convert(value);
64
+ }
56
65
  }
57
66
  else
58
67
  {
@@ -67,4 +76,23 @@ namespace Rice::detail
67
76
  {
68
77
  return "";
69
78
  }
70
- } // Rice
79
+
80
+ template<typename Attribute_T>
81
+ inline std::string NativeAttributeSet<Attribute_T>::name()
82
+ {
83
+ return this->name_;
84
+ }
85
+
86
+ template<typename Attribute_T>
87
+ inline NativeKind NativeAttributeSet<Attribute_T>::kind()
88
+ {
89
+ return NativeKind::AttributeWriter;
90
+ }
91
+
92
+ template<typename Attribute_T>
93
+ inline VALUE NativeAttributeSet<Attribute_T>::returnKlass()
94
+ {
95
+ TypeMapper<Attr_T> typeMapper;
96
+ return typeMapper.rubyKlass();
97
+ }
98
+ }
@@ -64,7 +64,7 @@ namespace Rice::detail
64
64
  on the arguments (Arg_Ts) required by the C++ function. Arg_T may have const/volatile while
65
65
  the associated From_Ruby<T> template parameter will not. Thus From_Ruby produces non-const values
66
66
  which we let the compiler convert to const values as needed. This works except for
67
- T** -> const T**, see comment in getNativeValue method. */
67
+ T** -> const T**, see comment in convertToNative method. */
68
68
  return std::forward_as_tuple(*(std::tuple_element_t<I, Tuple_T>*)(args[I])...);
69
69
  }
70
70
 
@@ -137,7 +137,7 @@ namespace Rice::detail
137
137
  VALUE result = detail::protect(rb_funcallv, this->proc_, id.id(), (int)sizeof...(Arg_Ts), values.data());
138
138
  if constexpr (!std::is_void_v<Return_T>)
139
139
  {
140
- static From_Ruby<Return_T> fromRuby(dynamic_cast<Arg*>(&methodInfo_->returnInfo));
140
+ static From_Ruby<Return_T> fromRuby(dynamic_cast<Arg*>(methodInfo_->returnInfo()));
141
141
  return fromRuby.convert(result);
142
142
  }
143
143
  }
@@ -15,7 +15,7 @@ namespace Rice::detail
15
15
  VALUE result = detail::protect(rb_funcallv, proc, id.id(), (int)sizeof...(Arg_Ts), values.data());
16
16
  if constexpr (!std::is_void_v<Return_T>)
17
17
  {
18
- static From_Ruby<Return_T> fromRuby(dynamic_cast<Arg*>(&methodInfo_->returnInfo));
18
+ static From_Ruby<Return_T> fromRuby(dynamic_cast<Arg*>(methodInfo_->returnInfo()));
19
19
  return fromRuby.convert(result);
20
20
  }
21
21
  }