rice 4.8.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 (68) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +25 -1
  3. data/CMakePresets.json +77 -50
  4. data/FindRuby.cmake +1 -1
  5. data/bin/rice-doc.rb +2 -0
  6. data/include/rice/api.hpp +14 -1
  7. data/include/rice/rice.hpp +351 -132
  8. data/include/rice/stl.hpp +319 -256
  9. data/lib/rice/doc/config.rb +57 -57
  10. data/lib/rice/doc/cpp_reference.rb +158 -158
  11. data/lib/rice/doc/doxygen.rb +289 -289
  12. data/lib/rice/doc/mkdocs.rb +332 -332
  13. data/lib/rice/doc/rice.rb +48 -47
  14. data/lib/rice/doc/ruby.rb +26 -26
  15. data/lib/rice/native.rb +15 -15
  16. data/lib/rice/native_registry.rb +12 -17
  17. data/lib/rice/parameter.rb +5 -5
  18. data/lib/rice/rbs.rb +72 -72
  19. data/lib/rice/version.rb +1 -1
  20. data/lib/rubygems/builder.rb +9 -9
  21. data/lib/rubygems_plugin.rb +8 -8
  22. data/rice/Data_Type.ipp +12 -7
  23. data/rice/cpp_api/Class.hpp +5 -0
  24. data/rice/cpp_api/Class.ipp +5 -0
  25. data/rice/cpp_api/Object.hpp +6 -0
  26. data/rice/cpp_api/Object.ipp +5 -0
  27. data/rice/detail/Forwards.hpp +18 -0
  28. data/rice/detail/Forwards.ipp +60 -0
  29. data/rice/detail/Native.ipp +2 -4
  30. data/rice/detail/NativeAttributeGet.ipp +1 -1
  31. data/rice/detail/NativeAttributeSet.hpp +5 -3
  32. data/rice/detail/NativeAttributeSet.ipp +41 -33
  33. data/rice/detail/NativeMethod.ipp +25 -22
  34. data/rice/detail/NativeRegistry.hpp +4 -2
  35. data/rice/detail/NativeRegistry.ipp +42 -9
  36. data/rice/detail/Parameter.ipp +3 -4
  37. data/rice/detail/Type.ipp +4 -0
  38. data/rice/detail/Wrapper.hpp +17 -12
  39. data/rice/detail/Wrapper.ipp +95 -36
  40. data/rice/rice.hpp +3 -0
  41. data/rice/rice_api/NativeRegistry.ipp +14 -1
  42. data/rice/stl/exception.ipp +1 -1
  43. data/rice/stl/filesystem.ipp +1 -1
  44. data/rice/stl/map.ipp +13 -11
  45. data/rice/stl/multimap.ipp +13 -11
  46. data/rice/stl/pair.ipp +14 -8
  47. data/rice/stl/set.ipp +16 -16
  48. data/rice/stl/shared_ptr.hpp +16 -0
  49. data/rice/stl/shared_ptr.ipp +74 -37
  50. data/rice/stl/type_index.ipp +1 -1
  51. data/rice/stl/unique_ptr.hpp +9 -3
  52. data/rice/stl/unique_ptr.ipp +80 -124
  53. data/rice/stl/unordered_map.ipp +14 -12
  54. data/rice/stl/vector.ipp +67 -31
  55. data/test/test_Attribute.cpp +72 -0
  56. data/test/test_Callback.cpp +3 -0
  57. data/test/test_Inheritance.cpp +14 -14
  58. data/test/test_Keep_Alive_No_Wrapper.cpp +6 -2
  59. data/test/test_Stl_Map.cpp +46 -0
  60. data/test/test_Stl_Multimap.cpp +46 -0
  61. data/test/test_Stl_Set.cpp +34 -0
  62. data/test/test_Stl_SharedPtr.cpp +160 -45
  63. data/test/test_Stl_UniquePtr.cpp +48 -3
  64. data/test/test_Stl_Unordered_Map.cpp +46 -0
  65. data/test/test_Stl_Variant.cpp +10 -14
  66. data/test/test_Stl_Vector.cpp +140 -13
  67. data/test/test_Tracking.cpp +3 -0
  68. metadata +3 -1
data/lib/rice/doc/rice.rb CHANGED
@@ -1,49 +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
- }
10
-
11
- def class_url(klass)
12
- CLASS_DOCS.each do |pattern, path|
13
- if klass.name.match?(pattern)
14
- return "#{ROOT}/#{path}"
15
- end
16
- end
17
- nil
18
- end
19
-
20
- def module_url(klass)
21
- nil
22
- end
23
-
24
- def union_url(klass)
25
- nil
26
- end
27
-
28
- def enum_url(klass)
29
- nil
30
- end
31
-
32
- def enum_value_url(klass, enum_value)
33
- nil
34
- end
35
-
36
- def singleton_method_url(klass, native)
37
- nil
38
- end
39
-
40
- def method_url(klass, native)
41
- class_url(klass)
42
- end
43
-
44
- def attribute_url(klass, native)
45
- nil
46
- end
47
- end
48
- 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
49
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,21 +1,16 @@
1
1
  module Rice
2
- class NativeRegistry
3
- def native_attributes(klass)
4
- self.native_by_kind(klass, [Rice::NativeKind::AttributeReader, Rice::NativeKind::AttributeWriter])
5
- 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
6
7
 
7
- def native_methods(klass)
8
- self.native_by_kind(klass, [Rice::NativeKind::Method])
9
- end
8
+ def native_methods(klass)
9
+ self.lookup_by_kind(klass, Rice::NativeKind::Method)
10
+ end
10
11
 
11
- def native_functions(klass)
12
- self.native_by_kind(klass, [Rice::NativeKind::Function])
13
- end
14
-
15
- def native_by_kind(klass, kinds)
16
- self.lookup(klass).find_all do |native|
17
- kinds.include?(native.kind)
18
- end
19
- end
20
- end
12
+ def native_functions(klass)
13
+ self.lookup_by_kind(klass, Rice::NativeKind::Function)
14
+ end
15
+ end
21
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"
15
- require self.extension
16
- types = Registries.instance.types
17
- types.klasses.each do |klass|
18
- process_class(klass)
19
- end
20
- end
13
+ def generate
14
+ STDOUT << "Writing rbs files to #{@output}" << "\n"
21
15
 
22
- def process_class(klass)
23
- if ['Rice', 'Std'].include?(klass.name.split('::').first)
24
- return
25
- end
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
26
19
 
27
- STDOUT << " " << klass << "\n"
20
+ types = Registries.instance.types
21
+ types.klasses.each do |klass|
22
+ process_class(klass)
23
+ end
24
+ end
28
25
 
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
26
+ def process_class(klass)
27
+ STDOUT << " " << klass << "\n"
38
28
 
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)
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
44
38
 
45
- path = File.join(dir, file_name)
46
- File.write(path, content, mode: "wb")
47
- end
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)
48
44
 
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
45
+ path = File.join(dir, file_name)
46
+ File.write(path, content, mode: "wb")
47
+ end
59
48
 
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
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
67
59
 
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
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
74
67
 
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
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
83
74
 
84
- def template
85
- <<~EOS
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
+
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.8.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
@@ -5,17 +5,22 @@ namespace Rice
5
5
  template<typename T>
6
6
  inline void ruby_mark_internal(detail::WrapperBase* wrapper)
7
7
  {
8
- // Tell the wrapper to mark the objects its keeping alive
9
- wrapper->ruby_mark();
10
-
11
- // Get the underlying data and call custom mark function (if any)
12
- T* data = static_cast<T*>(wrapper->get());
13
- ruby_mark<T>(data);
8
+ detail::cpp_protect([&]
9
+ {
10
+ // Tell the wrapper to mark the objects its keeping alive
11
+ wrapper->ruby_mark();
12
+
13
+ // Get the underlying data and call custom mark function (if any)
14
+ // Use the wrapper's stored rb_data_type to avoid type mismatch
15
+ T* data = static_cast<T*>(wrapper->get(Data_Type<T>::ruby_data_type()));
16
+ ruby_mark<T>(data);
17
+ });
14
18
  }
15
19
 
16
20
  template<typename T>
17
21
  inline void ruby_free_internal(detail::WrapperBase* wrapper)
18
22
  {
23
+ // Destructors are noexcept so we cannot use cpp_protect here
19
24
  delete wrapper;
20
25
  }
21
26
 
@@ -380,7 +385,7 @@ namespace Rice
380
385
  }
381
386
  else
382
387
  {
383
- 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...);
384
389
  }
385
390
  }
386
391
 
@@ -37,6 +37,11 @@ namespace Rice
37
37
  */
38
38
  const std::string base_name() const;
39
39
 
40
+ //! Return the superclass of this class
41
+ /*! \return Class.
42
+ */
43
+ Class superclass() const;
44
+
40
45
  #include "shared_methods.hpp"
41
46
  };
42
47
 
@@ -33,6 +33,11 @@ namespace Rice
33
33
  return result;
34
34
  }
35
35
 
36
+ inline Class Class::superclass() const
37
+ {
38
+ return detail::protect(rb_class_superclass, this->value());
39
+ }
40
+
36
41
  inline Class define_class_under(Object parent, Identifier id, const Class& superclass)
37
42
  {
38
43
  VALUE klass = detail::protect(rb_define_class_id_under, parent.value(), id, superclass.value());
@@ -9,6 +9,7 @@
9
9
  namespace Rice
10
10
  {
11
11
  class Class;
12
+ class Module;
12
13
  class String;
13
14
  class Array;
14
15
 
@@ -116,6 +117,11 @@ namespace Rice
116
117
  */
117
118
  bool is_a(Object klass) const;
118
119
 
120
+ //! Extend the object with a module.
121
+ /*! \param mod the module to extend with.
122
+ */
123
+ void extend(Module const& mod);
124
+
119
125
  //! Determine if the objects responds to a method.
120
126
  /*! \param id the name of the method
121
127
  * \return true if the objects responds to the method, false
@@ -99,6 +99,11 @@ namespace Rice
99
99
  return RB_TEST(result);
100
100
  }
101
101
 
102
+ inline void Object::extend(Module const& mod)
103
+ {
104
+ detail::protect(rb_extend_object, this->value(), mod.value());
105
+ }
106
+
102
107
  inline bool Object::respond_to(Identifier id) const
103
108
  {
104
109
  return bool(rb_respond_to(this->value(), id.id()));
@@ -0,0 +1,18 @@
1
+ #ifndef Rice__detail__Forwards__hpp_
2
+ #define Rice__detail__Forwards__hpp_
3
+
4
+ namespace Rice::detail
5
+ {
6
+ // Setup method forwarding from a wrapper class to its wrapped type using Ruby's Forwardable.
7
+ // This allows calling methods on the wrapper that get delegated to the wrapped object via
8
+ // a "get" method that returns the wrapped object.
9
+ //
10
+ // Parameters:
11
+ // wrapper_klass - The Ruby class to add forwarding to (e.g., SharedPtr_MyClass)
12
+ // wrapped_klass - The Ruby class whose methods should be forwarded (e.g., MyClass)
13
+ void define_forwarding(VALUE wrapper_klass, VALUE wrapped_klass);
14
+ }
15
+
16
+ #include "Forwards.ipp"
17
+
18
+ #endif // Rice__detail__Forwards__hpp_
@@ -0,0 +1,60 @@
1
+ namespace Rice::detail
2
+ {
3
+ inline void define_forwarding(VALUE wrapper_klass, VALUE wrapped_klass)
4
+ {
5
+ protect(rb_require, "forwardable");
6
+ Object forwardable = Object(rb_cObject).const_get("Forwardable");
7
+ Object(wrapper_klass).extend(forwardable.value());
8
+
9
+ // Get wrapper class's method names to avoid conflicts
10
+ std::set<std::string> wrapperMethodSet;
11
+ for (Native* native : Registries::instance.natives.lookup(wrapper_klass, NativeKind::Method))
12
+ {
13
+ wrapperMethodSet.insert(native->name());
14
+ }
15
+ for (Native* native : Registries::instance.natives.lookup(wrapper_klass, NativeKind::AttributeReader))
16
+ {
17
+ wrapperMethodSet.insert(native->name());
18
+ }
19
+ for (Native* native : Registries::instance.natives.lookup(wrapper_klass, NativeKind::AttributeWriter))
20
+ {
21
+ wrapperMethodSet.insert(native->name() + "=");
22
+ }
23
+
24
+ // Get wrapped class's method names from the registry, including ancestor classes
25
+ std::set<std::string> wrappedMethodSet;
26
+ Class klass(wrapped_klass);
27
+ while (klass.value() != rb_cObject && klass.value() != Qnil)
28
+ {
29
+ for (Native* native : Registries::instance.natives.lookup(klass.value(), NativeKind::Method))
30
+ {
31
+ wrappedMethodSet.insert(native->name());
32
+ }
33
+ for (Native* native : Registries::instance.natives.lookup(klass.value(), NativeKind::AttributeReader))
34
+ {
35
+ wrappedMethodSet.insert(native->name());
36
+ }
37
+ for (Native* native : Registries::instance.natives.lookup(klass.value(), NativeKind::AttributeWriter))
38
+ {
39
+ wrappedMethodSet.insert(native->name() + "=");
40
+ }
41
+
42
+ klass = klass.superclass();
43
+ }
44
+
45
+ // Build the arguments array for def_delegators: [:get, :method1, :method2, ...]
46
+ // Skip methods that are already defined on the wrapper class
47
+ Array args;
48
+ args.push(Symbol("get"));
49
+ for (const std::string& method : wrappedMethodSet)
50
+ {
51
+ if (wrapperMethodSet.find(method) == wrapperMethodSet.end())
52
+ {
53
+ args.push(Symbol(method));
54
+ }
55
+ }
56
+
57
+ // Call def_delegators(*args)
58
+ Object(wrapper_klass).vcall("def_delegators", args);
59
+ }
60
+ }
@@ -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