rice 4.9.0 → 4.9.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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +17 -1
  3. data/CMakePresets.json +77 -50
  4. data/FindRuby.cmake +1 -1
  5. data/include/rice/rice.hpp +114 -81
  6. data/include/rice/stl.hpp +157 -95
  7. data/lib/rice/doc/config.rb +57 -57
  8. data/lib/rice/doc/cpp_reference.rb +158 -158
  9. data/lib/rice/doc/doxygen.rb +289 -289
  10. data/lib/rice/doc/mkdocs.rb +332 -332
  11. data/lib/rice/doc/rice.rb +48 -48
  12. data/lib/rice/doc/ruby.rb +26 -26
  13. data/lib/rice/native.rb +15 -15
  14. data/lib/rice/native_registry.rb +12 -12
  15. data/lib/rice/parameter.rb +5 -5
  16. data/lib/rice/rbs.rb +71 -71
  17. data/lib/rice/version.rb +1 -1
  18. data/lib/rubygems/builder.rb +9 -9
  19. data/lib/rubygems_plugin.rb +8 -8
  20. data/rice/Data_Type.ipp +1 -1
  21. data/rice/detail/Native.ipp +2 -4
  22. data/rice/detail/NativeAttributeGet.ipp +1 -1
  23. data/rice/detail/NativeAttributeSet.hpp +5 -3
  24. data/rice/detail/NativeAttributeSet.ipp +41 -33
  25. data/rice/detail/NativeMethod.ipp +25 -22
  26. data/rice/detail/NativeRegistry.hpp +3 -2
  27. data/rice/detail/NativeRegistry.ipp +13 -9
  28. data/rice/detail/Parameter.ipp +3 -4
  29. data/rice/detail/Wrapper.hpp +5 -1
  30. data/rice/detail/Wrapper.ipp +15 -1
  31. data/rice/stl/exception.ipp +1 -1
  32. data/rice/stl/filesystem.ipp +1 -1
  33. data/rice/stl/map.ipp +13 -11
  34. data/rice/stl/multimap.ipp +13 -11
  35. data/rice/stl/pair.ipp +14 -8
  36. data/rice/stl/set.ipp +16 -16
  37. data/rice/stl/shared_ptr.ipp +15 -1
  38. data/rice/stl/type_index.ipp +1 -1
  39. data/rice/stl/unique_ptr.ipp +2 -2
  40. data/rice/stl/unordered_map.ipp +14 -12
  41. data/rice/stl/vector.ipp +67 -31
  42. data/test/test_Attribute.cpp +72 -0
  43. data/test/test_Callback.cpp +3 -0
  44. data/test/test_Stl_Map.cpp +46 -0
  45. data/test/test_Stl_Multimap.cpp +46 -0
  46. data/test/test_Stl_Set.cpp +34 -0
  47. data/test/test_Stl_Unordered_Map.cpp +46 -0
  48. data/test/test_Stl_Variant.cpp +10 -14
  49. data/test/test_Stl_Vector.cpp +140 -13
  50. data/test/test_Tracking.cpp +3 -0
  51. metadata +1 -1
data/lib/rice/doc/rice.rb CHANGED
@@ -1,50 +1,50 @@
1
1
  module Rice
2
- module Doc
3
- class Rice
4
- ROOT = "https://ruby-rice.github.io/4.x"
5
-
6
- CLASS_DOCS = {
7
- /^Rice::Buffer/ => "ruby_api/buffer",
8
- /^Rice::Pointer/ => "ruby_api/pointer",
9
- /^Rice::Reference/ => "ruby_api/reference"
10
- }
11
-
12
- def class_url(klass)
13
- CLASS_DOCS.each do |pattern, path|
14
- if klass.name.match?(pattern)
15
- return "#{ROOT}/#{path}"
16
- end
17
- end
18
- nil
19
- end
20
-
21
- def module_url(klass)
22
- nil
23
- end
24
-
25
- def union_url(klass)
26
- nil
27
- end
28
-
29
- def enum_url(klass)
30
- nil
31
- end
32
-
33
- def enum_value_url(klass, enum_value)
34
- nil
35
- end
36
-
37
- def singleton_method_url(klass, native)
38
- nil
39
- end
40
-
41
- def method_url(klass, native)
42
- class_url(klass)
43
- end
44
-
45
- def attribute_url(klass, native)
46
- nil
47
- end
48
- end
49
- end
2
+ module Doc
3
+ class Rice
4
+ ROOT = "https://ruby-rice.github.io/4.x"
5
+
6
+ CLASS_DOCS = {
7
+ /^Rice::Buffer/ => "ruby_api/buffer",
8
+ /^Rice::Pointer/ => "ruby_api/pointer",
9
+ /^Rice::Reference/ => "ruby_api/reference"
10
+ }
11
+
12
+ def class_url(klass)
13
+ CLASS_DOCS.each do |pattern, path|
14
+ if klass.name.match?(pattern)
15
+ return "#{ROOT}/#{path}"
16
+ end
17
+ end
18
+ nil
19
+ end
20
+
21
+ def module_url(klass)
22
+ nil
23
+ end
24
+
25
+ def union_url(klass)
26
+ nil
27
+ end
28
+
29
+ def enum_url(klass)
30
+ nil
31
+ end
32
+
33
+ def enum_value_url(klass, enum_value)
34
+ nil
35
+ end
36
+
37
+ def singleton_method_url(klass, native)
38
+ nil
39
+ end
40
+
41
+ def method_url(klass, native)
42
+ class_url(klass)
43
+ end
44
+
45
+ def attribute_url(klass, native)
46
+ nil
47
+ end
48
+ end
49
+ end
50
50
  end
data/lib/rice/doc/ruby.rb CHANGED
@@ -1,37 +1,37 @@
1
1
  module Rice
2
- module Doc
3
- class Ruby
4
- ROOT = "https://docs.ruby-lang.org/en/master"
2
+ module Doc
3
+ class Ruby
4
+ ROOT = "https://docs.ruby-lang.org/en/master"
5
5
 
6
- def initialize
7
- end
6
+ def initialize
7
+ end
8
8
 
9
- def class_url(klass)
10
- name = klass.name.split('::').last
11
- name[0].upcase! # Can't use capitalize because it lowercases other letters which breaks links like NilClass
12
- "#{ROOT}/#{name}.html"
13
- end
9
+ def class_url(klass)
10
+ name = klass.name.split('::').last
11
+ name[0].upcase! # Can't use capitalize because it lowercases other letters which breaks links like NilClass
12
+ "#{ROOT}/#{name}.html"
13
+ end
14
14
 
15
- def module_url(klass)
16
- end
15
+ def module_url(klass)
16
+ end
17
17
 
18
- def union_url(klass)
19
- end
18
+ def union_url(klass)
19
+ end
20
20
 
21
- def enum_url(klass)
22
- end
21
+ def enum_url(klass)
22
+ end
23
23
 
24
- def enum_value_url(klass, enum_value)
25
- end
24
+ def enum_value_url(klass, enum_value)
25
+ end
26
26
 
27
- def singleton_method_url(klass, native)
28
- end
27
+ def singleton_method_url(klass, native)
28
+ end
29
29
 
30
- def method_url(klass, native)
31
- end
30
+ def method_url(klass, native)
31
+ end
32
32
 
33
- def attribute_url(klass, native)
34
- end
35
- end
36
- end
33
+ def attribute_url(klass, native)
34
+ end
35
+ end
36
+ end
37
37
  end
data/lib/rice/native.rb CHANGED
@@ -1,18 +1,18 @@
1
1
  module Rice
2
- class Native
3
- include Comparable
2
+ class Native
3
+ include Comparable
4
4
 
5
- def <=>(other)
6
- case
7
- when self.name == other.name
8
- self.parameters.size <=> other.parameters.size
9
- when self.name == "initialize"
10
- -1
11
- when self.name == "initialize"
12
- 1
13
- else
14
- self.name <=> other.name
15
- end
16
- end
17
- end
5
+ def <=>(other)
6
+ case
7
+ when self.name == other.name
8
+ self.parameters.size <=> other.parameters.size
9
+ when self.name == "initialize"
10
+ -1
11
+ when self.name == "initialize"
12
+ 1
13
+ else
14
+ self.name <=> other.name
15
+ end
16
+ end
17
+ end
18
18
  end
@@ -1,16 +1,16 @@
1
1
  module Rice
2
- class NativeRegistry
3
- def native_attributes(klass)
4
- self.lookup_by_kind(klass, Rice::NativeKind::AttributeReader) +
5
- self.lookup_by_kind(klass, Rice::NativeKind::AttributeWriter)
6
- end
2
+ class NativeRegistry
3
+ def native_attributes(klass)
4
+ self.lookup_by_kind(klass, Rice::NativeKind::AttributeReader) +
5
+ self.lookup_by_kind(klass, Rice::NativeKind::AttributeWriter)
6
+ end
7
7
 
8
- def native_methods(klass)
9
- self.lookup_by_kind(klass, Rice::NativeKind::Method)
10
- end
8
+ def native_methods(klass)
9
+ self.lookup_by_kind(klass, Rice::NativeKind::Method)
10
+ end
11
11
 
12
- def native_functions(klass)
13
- self.lookup_by_kind(klass, Rice::NativeKind::Function)
14
- end
15
- end
12
+ def native_functions(klass)
13
+ self.lookup_by_kind(klass, Rice::NativeKind::Function)
14
+ end
15
+ end
16
16
  end
@@ -1,7 +1,7 @@
1
1
  module Rice
2
- class Parameter
3
- def to_s
4
- "Parameter<#{self.arg.name}: #{self.klass.name}>"
5
- end
6
- end
2
+ class Parameter
3
+ def to_s
4
+ "Parameter<#{self.arg.name}: #{self.klass.name}>"
5
+ end
6
+ end
7
7
  end
data/lib/rice/rbs.rb CHANGED
@@ -2,87 +2,87 @@ require 'erb'
2
2
  require 'fileutils'
3
3
 
4
4
  module Rice
5
- class Rbs
6
- attr_reader :extension, :output
5
+ class Rbs
6
+ attr_reader :extension, :output
7
7
 
8
- def initialize(extension, output)
9
- @extension = extension
10
- @output = output
11
- end
8
+ def initialize(extension, output)
9
+ @extension = extension
10
+ @output = output
11
+ end
12
12
 
13
- def generate
14
- STDOUT << "Writing rbs files to #{@output}" << "\n"
13
+ def generate
14
+ STDOUT << "Writing rbs files to #{@output}" << "\n"
15
15
 
16
- # Add the extension directory the path in case it ships with extra libraries
17
- ENV["PATH"] = "#{File.dirname(self.extension)}#{File::PATH_SEPARATOR}#{ENV["PATH"]}"
18
- require self.extension
16
+ # Add the extension directory the path in case it ships with extra libraries
17
+ ENV["PATH"] = "#{File.dirname(self.extension)}#{File::PATH_SEPARATOR}#{ENV["PATH"]}"
18
+ require self.extension
19
19
 
20
- types = Registries.instance.types
21
- types.klasses.each do |klass|
22
- process_class(klass)
23
- end
24
- end
20
+ types = Registries.instance.types
21
+ types.klasses.each do |klass|
22
+ process_class(klass)
23
+ end
24
+ end
25
25
 
26
- def process_class(klass)
27
- STDOUT << " " << klass << "\n"
26
+ def process_class(klass)
27
+ STDOUT << " " << klass << "\n"
28
28
 
29
- native_attributes = Registries.instance.natives.native_attributes(klass).sort.group_by(&:name)
30
- native_functions = Registries.instance.natives.native_functions(klass).sort.group_by(&:name)
31
- native_methods = Registries.instance.natives.native_methods(klass).sort.group_by(&:name)
32
- content = render_template("class", :klass => klass,
33
- :native_attributes => native_attributes,
34
- :native_functions => native_functions,
35
- :native_methods => native_methods)
36
- write_file(klass, content)
37
- end
29
+ native_attributes = Registries.instance.natives.native_attributes(klass).sort.group_by(&:name)
30
+ native_functions = Registries.instance.natives.native_functions(klass).sort.group_by(&:name)
31
+ native_methods = Registries.instance.natives.native_methods(klass).sort.group_by(&:name)
32
+ content = render_template("class", :klass => klass,
33
+ :native_attributes => native_attributes,
34
+ :native_functions => native_functions,
35
+ :native_methods => native_methods)
36
+ write_file(klass, content)
37
+ end
38
38
 
39
- def write_file(klass, content)
40
- parts = klass.name.split("::")
41
- file_name = "#{parts.pop}.rbs"
42
- dir = File.join(self.output, *parts)
43
- FileUtils.mkdir_p(dir)
39
+ def write_file(klass, content)
40
+ parts = klass.name.split("::")
41
+ file_name = "#{parts.pop}.rbs"
42
+ dir = File.join(self.output, *parts)
43
+ FileUtils.mkdir_p(dir)
44
44
 
45
- path = File.join(dir, file_name)
46
- File.write(path, content, mode: "wb")
47
- end
45
+ path = File.join(dir, file_name)
46
+ File.write(path, content, mode: "wb")
47
+ end
48
48
 
49
- def attribute_sig(native_attributes)
50
- attr_type = if native_attributes.size == 2
51
- "attr_accessor"
52
- elsif native_attributes.first.kind == Rice::NativeKind::AttributeReader
53
- "attr_reader"
54
- else
55
- "attr_writer"
56
- end
57
- "#{attr_type} #{native_attributes.first.name}: #{native_attributes.first.return_klass}"
58
- end
49
+ def attribute_sig(native_attributes)
50
+ attr_type = if native_attributes.size == 2
51
+ "attr_accessor"
52
+ elsif native_attributes.first.kind == Rice::NativeKind::AttributeReader
53
+ "attr_reader"
54
+ else
55
+ "attr_writer"
56
+ end
57
+ "#{attr_type} #{native_attributes.first.name}: #{native_attributes.first.return_klass}"
58
+ end
59
59
 
60
- def method_sigs(native_methods, indent = 0)
61
- join_string = "\n" + (" " * indent) + "| "
62
- a = native_methods.map do |native_method|
63
- method_sig(native_method)
64
- end
65
- a.join(join_string)
66
- end
60
+ def method_sigs(native_methods, indent = 0)
61
+ join_string = "\n" + (" " * indent) + "| "
62
+ a = native_methods.map do |native_method|
63
+ method_sig(native_method)
64
+ end
65
+ a.join(join_string)
66
+ end
67
67
 
68
- def method_sig(native)
69
- params = native.parameters.map do |parameter|
70
- "#{parameter.arg.name}: #{parameter.klass}"
71
- end.join(", ")
72
- "(#{params}) -> #{native.return_klass}"
73
- end
68
+ def method_sig(native)
69
+ params = native.parameters.map do |parameter|
70
+ "#{parameter.arg.name}: #{parameter.klass}"
71
+ end.join(", ")
72
+ "(#{params}) -> #{native.return_klass}"
73
+ end
74
74
 
75
- def render_template(template, local_variables = {})
76
- template = ERB.new(self.template, :trim_mode => '-')
77
- b = self.binding
78
- local_variables.each do |key, value|
79
- b.local_variable_set(key, value)
80
- end
81
- template.result(b)
82
- end
75
+ def render_template(template, local_variables = {})
76
+ template = ERB.new(self.template, :trim_mode => '-')
77
+ b = self.binding
78
+ local_variables.each do |key, value|
79
+ b.local_variable_set(key, value)
80
+ end
81
+ template.result(b)
82
+ end
83
83
 
84
- def template
85
- <<~EOS
84
+ def template
85
+ <<~EOS
86
86
  module <%= klass.name.split("::")[0..-2].join("::") %>
87
87
  class <%= klass.name.split("::").last %>
88
88
  <%- native_functions.each do |name, functions| -%>
@@ -98,7 +98,7 @@ module Rice
98
98
  <%- end -%>
99
99
  end
100
100
  end
101
- EOS
102
- end
103
- end
101
+ EOS
102
+ end
103
+ end
104
104
  end
data/lib/rice/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Rice
2
- VERSION = "4.9.0"
2
+ VERSION = "4.9.1"
3
3
  end
@@ -1,11 +1,11 @@
1
1
  class Gem::Ext::Builder
2
- alias :builder_for_original :builder_for
3
- def builder_for(extension)
4
- case extension
5
- when /CMakeLists.txt/ then
6
- Gem::Ext::CmakeBuilder.new
7
- else
8
- builder_for_original(extension)
9
- end
10
- end
2
+ alias :builder_for_original :builder_for
3
+ def builder_for(extension)
4
+ case extension
5
+ when /CMakeLists.txt/ then
6
+ Gem::Ext::CmakeBuilder.new
7
+ else
8
+ builder_for_original(extension)
9
+ end
10
+ end
11
11
  end
@@ -1,12 +1,12 @@
1
1
  # For older versions of RubyGems replace the default CMakeBuilder with a
2
2
  # more modern one
3
3
  if Gem.rubygems_version < Gem::Version.new('4.0')
4
- Gem.pre_install do |installer|
5
- extensions = installer.package&.spec&.extensions
6
- if extensions && extensions.grep(/CMakeLists/)
7
- require_relative 'rubygems/builder'
8
- require_relative 'rubygems/cmake_builder'
9
- end
10
- true
11
- end
4
+ Gem.pre_install do |installer|
5
+ extensions = installer.package&.spec&.extensions
6
+ if extensions && extensions.grep(/CMakeLists/)
7
+ require_relative 'rubygems/builder'
8
+ require_relative 'rubygems/cmake_builder'
9
+ end
10
+ true
11
+ end
12
12
  end
data/rice/Data_Type.ipp CHANGED
@@ -385,7 +385,7 @@ namespace Rice
385
385
  }
386
386
  else
387
387
  {
388
- detail::NativeAttributeSet<Attribute_T>::define(klass, name, std::forward<Attribute_T>(attribute));
388
+ detail::NativeAttributeSet<Attribute_T>::define(klass, name, std::forward<Attribute_T>(attribute), args...);
389
389
  }
390
390
  }
391
391
 
@@ -176,16 +176,14 @@ namespace Rice::detail
176
176
  Arg* arg = parameters_[i]->arg();
177
177
  if (arg->isKeepAlive())
178
178
  {
179
- static WrapperBase* selfWrapper = getWrapper(self);
180
- selfWrapper->addKeepAlive(rubyValues[i].value());
179
+ WrapperBase::addKeepAlive(self, rubyValues[i].value());
181
180
  }
182
181
  }
183
182
 
184
183
  // Check return value
185
184
  if (this->returnInfo_->isKeepAlive())
186
185
  {
187
- WrapperBase* returnWrapper = getWrapper(returnValue);
188
- returnWrapper->addKeepAlive(self);
186
+ WrapperBase::addKeepAlive(returnValue, self);
189
187
  }
190
188
  }
191
189
 
@@ -23,7 +23,7 @@ namespace Rice::detail
23
23
  // matches or calls function pointer. Instead Ruby can call the static call method defined on
24
24
  // this class (&NativeAttribute_T::get).
25
25
  Identifier identifier(name);
26
- detail::Registries::instance.natives.add(klass, identifier.id(), native);
26
+ detail::Registries::instance.natives.replace(klass, identifier.id(), native);
27
27
  }
28
28
 
29
29
  template<typename Attribute_T>
@@ -15,8 +15,9 @@ namespace Rice
15
15
  using Receiver_T = typename attribute_traits<Attribute_T>::class_type;
16
16
 
17
17
  public:
18
- // Register attribute getter/setter with Ruby
19
- static void define(VALUE klass, std::string name, Attribute_T attribute);
18
+ // Register attribute setter with Ruby
19
+ template<typename...Arg_Ts>
20
+ static void define(VALUE klass, std::string name, Attribute_T attribute, Arg_Ts&...args);
20
21
 
21
22
  public:
22
23
  // Disallow creating/copying/moving
@@ -34,11 +35,12 @@ namespace Rice
34
35
  VALUE returnKlass() override;
35
36
 
36
37
  protected:
37
- NativeAttributeSet(VALUE klass, std::string name, Attribute_T attr);
38
+ NativeAttributeSet(VALUE klass, std::string name, Attribute_T attr, std::unique_ptr<Parameter<T_Unqualified>> parameter);
38
39
 
39
40
  private:
40
41
  VALUE klass_;
41
42
  Attribute_T attribute_;
43
+ std::unique_ptr<Parameter<T_Unqualified>> parameter_;
42
44
  };
43
45
  } // detail
44
46
  } // Rice
@@ -5,28 +5,46 @@
5
5
  namespace Rice::detail
6
6
  {
7
7
  template<typename Attribute_T>
8
- void NativeAttributeSet<Attribute_T>::define(VALUE klass, std::string name, Attribute_T attribute)
8
+ template<typename...Arg_Ts>
9
+ void NativeAttributeSet<Attribute_T>::define(VALUE klass, std::string name, Attribute_T attribute, Arg_Ts&...args)
9
10
  {
10
- // Create a NativeAttributeSet that Ruby will call to read/write C++ variables
11
- NativeAttribute_T* nativeAttribute = new NativeAttribute_T(klass, name, std::forward<Attribute_T>(attribute));
11
+ // Extract Arg from Arg_Ts if present, otherwise create default
12
+ using Arg_Tuple = std::tuple<Arg_Ts...>;
13
+ constexpr std::size_t index = tuple_element_index_v<Arg_Tuple, Arg, ArgBuffer>;
14
+
15
+ std::unique_ptr<Arg> arg;
16
+ if constexpr (index < std::tuple_size_v<Arg_Tuple>)
17
+ {
18
+ using Arg_T_Local = std::decay_t<std::tuple_element_t<index, Arg_Tuple>>;
19
+ const Arg_T_Local& argInfo = std::get<index>(std::forward_as_tuple(std::forward<Arg_Ts>(args)...));
20
+ arg = std::make_unique<Arg_T_Local>(argInfo);
21
+ }
22
+ else
23
+ {
24
+ arg = std::make_unique<Arg>("value");
25
+ }
26
+
27
+ // Create the parameter
28
+ auto parameter = std::make_unique<Parameter<T_Unqualified>>(std::move(arg));
29
+
30
+ // Create a NativeAttributeSet that Ruby will call to write C++ variables
31
+ NativeAttribute_T* nativeAttribute = new NativeAttribute_T(klass, name, std::forward<Attribute_T>(attribute), std::move(parameter));
12
32
  std::unique_ptr<Native> native(nativeAttribute);
13
33
 
14
34
  // Define the write method name
15
35
  std::string setter = name + "=";
16
36
 
17
- // Tell Ruby to invoke the static method write to get the attribute value
37
+ // Tell Ruby to invoke the static method resolve to set the attribute value
18
38
  detail::protect(rb_define_method, klass, setter.c_str(), (RUBY_METHOD_FUNC)&Native::resolve, -1);
19
39
 
20
- // Add to native registry. Since attributes cannot be overridden, there is no need to set the
21
- // matches or calls function pointer. Instead Ruby can call the static call method defined on
22
- // this class (&NativeAttribute_T::set).
40
+ // Add to native registry
23
41
  Identifier identifier(setter);
24
- detail::Registries::instance.natives.add(klass, identifier.id(), native);
42
+ detail::Registries::instance.natives.replace(klass, identifier.id(), native);
25
43
  }
26
44
 
27
45
  template<typename Attribute_T>
28
- NativeAttributeSet<Attribute_T>::NativeAttributeSet(VALUE klass, std::string name, Attribute_T attribute)
29
- : Native(name), klass_(klass), attribute_(attribute)
46
+ NativeAttributeSet<Attribute_T>::NativeAttributeSet(VALUE klass, std::string name, Attribute_T attribute, std::unique_ptr<Parameter<T_Unqualified>> parameter)
47
+ : Native(name), klass_(klass), attribute_(attribute), parameter_(std::move(parameter))
30
48
  {
31
49
  }
32
50
 
@@ -47,25 +65,25 @@ namespace Rice::detail
47
65
  throw std::runtime_error("Incorrect number of parameters for setting attribute. Attribute: " + this->name_);
48
66
  }
49
67
 
68
+ // Get the Ruby value and convert to native
50
69
  VALUE value = values.begin()->second;
70
+ std::optional<VALUE> valueOpt(value);
71
+ T_Unqualified nativeValue = this->parameter_->convertToNative(valueOpt);
51
72
 
52
73
  if constexpr (!std::is_null_pointer_v<Receiver_T>)
53
74
  {
54
75
  Receiver_T* nativeSelf = From_Ruby<Receiver_T*>().convert(self);
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
- }
76
+ nativeSelf->*attribute_ = (Attr_T)nativeValue;
65
77
  }
66
78
  else
67
79
  {
68
- *attribute_ = From_Ruby<T_Unqualified>().convert(value);
80
+ *attribute_ = nativeValue;
81
+ }
82
+
83
+ // Check if we need to prevent the value from being garbage collected
84
+ if (this->parameter_->arg()->isKeepAlive())
85
+ {
86
+ WrapperBase::addKeepAlive(self, value);
69
87
  }
70
88
 
71
89
  return value;
@@ -86,17 +104,7 @@ namespace Rice::detail
86
104
  template<typename Attribute_T>
87
105
  inline VALUE NativeAttributeSet<Attribute_T>::returnKlass()
88
106
  {
89
- // Check if an array is being returned
90
- bool isBuffer = dynamic_cast<ReturnBuffer*>(this->returnInfo_.get()) ? true : false;
91
- if (isBuffer)
92
- {
93
- TypeMapper<Pointer<detail::remove_cv_recursive_t<std::remove_pointer_t<Attr_T>>>> typeMapper;
94
- return typeMapper.rubyKlass();
95
- }
96
- else
97
- {
98
- TypeMapper<Attr_T> typeMapper;
99
- return typeMapper.rubyKlass();
100
- }
107
+ TypeMapper<Attr_T> typeMapper;
108
+ return typeMapper.rubyKlass();
101
109
  }
102
110
  }