rice 4.0.4 → 4.1.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.
- checksums.yaml +4 -4
 - data/CHANGELOG.md +30 -0
 - data/Rakefile +1 -1
 - data/include/rice/rice.hpp +2596 -1771
 - data/include/rice/stl.hpp +1580 -271
 - data/lib/mkmf-rice.rb +5 -2
 - data/lib/version.rb +1 -1
 - data/rice/Arg.hpp +6 -6
 - data/rice/Arg.ipp +8 -9
 - data/rice/Constructor.hpp +2 -2
 - data/rice/Data_Object.ipp +69 -15
 - data/rice/Data_Object_defn.hpp +1 -15
 - data/rice/Data_Type.ipp +56 -86
 - data/rice/Data_Type_defn.hpp +14 -17
 - data/rice/Director.hpp +0 -1
 - data/rice/Enum.ipp +31 -22
 - data/rice/Exception.ipp +2 -3
 - data/rice/Exception_defn.hpp +5 -5
 - data/rice/HandlerRegistration.hpp +15 -0
 - data/rice/Return.hpp +5 -4
 - data/rice/Return.ipp +8 -3
 - data/rice/detail/ExceptionHandler.hpp +8 -0
 - data/rice/detail/ExceptionHandler.ipp +28 -0
 - data/rice/detail/{Exception_Handler_defn.hpp → ExceptionHandler_defn.hpp} +17 -21
 - data/rice/detail/HandlerRegistry.hpp +51 -0
 - data/rice/detail/HandlerRegistry.ipp +20 -0
 - data/rice/detail/InstanceRegistry.hpp +34 -0
 - data/rice/detail/InstanceRegistry.ipp +50 -0
 - data/rice/detail/MethodInfo.ipp +1 -1
 - data/rice/detail/NativeAttribute.hpp +26 -15
 - data/rice/detail/NativeAttribute.ipp +76 -47
 - data/rice/detail/NativeFunction.hpp +60 -13
 - data/rice/detail/NativeFunction.ipp +103 -85
 - data/rice/detail/NativeIterator.hpp +49 -0
 - data/rice/detail/NativeIterator.ipp +102 -0
 - data/rice/detail/NativeRegistry.hpp +31 -0
 - data/rice/detail/{method_data.ipp → NativeRegistry.ipp} +20 -16
 - data/rice/detail/Registries.hpp +26 -0
 - data/rice/detail/Registries.ipp +23 -0
 - data/rice/detail/RubyFunction.hpp +6 -11
 - data/rice/detail/RubyFunction.ipp +10 -22
 - data/rice/detail/Type.hpp +1 -1
 - data/rice/detail/Type.ipp +2 -2
 - data/rice/detail/TypeRegistry.hpp +8 -11
 - data/rice/detail/TypeRegistry.ipp +3 -28
 - data/rice/detail/Wrapper.hpp +0 -2
 - data/rice/detail/Wrapper.ipp +73 -23
 - data/rice/detail/cpp_protect.hpp +93 -0
 - data/rice/detail/default_allocation_func.ipp +1 -1
 - data/rice/detail/from_ruby.ipp +206 -2
 - data/rice/detail/to_ruby.ipp +39 -5
 - data/rice/detail/to_ruby_defn.hpp +1 -1
 - data/rice/forward_declares.ipp +6 -0
 - data/rice/global_function.hpp +0 -4
 - data/rice/global_function.ipp +0 -6
 - data/rice/rice.hpp +29 -24
 - data/rice/stl.hpp +6 -1
 - data/test/embed_ruby.cpp +0 -15
 - data/test/test_Array.cpp +20 -24
 - data/test/test_Class.cpp +8 -47
 - data/test/test_Constructor.cpp +0 -2
 - data/test/test_Data_Object.cpp +25 -11
 - data/test/test_Data_Type.cpp +124 -28
 - data/test/test_Director.cpp +12 -13
 - data/test/test_Enum.cpp +65 -26
 - data/test/test_Inheritance.cpp +9 -9
 - data/test/test_Iterator.cpp +134 -5
 - data/test/test_Keep_Alive.cpp +7 -7
 - data/test/test_Memory_Management.cpp +1 -1
 - data/test/test_Module.cpp +25 -62
 - data/test/test_Object.cpp +66 -3
 - data/test/test_Ownership.cpp +12 -13
 - data/test/test_Self.cpp +12 -13
 - data/test/test_Stl_Map.cpp +696 -0
 - data/test/test_Stl_Optional.cpp +3 -3
 - data/test/test_Stl_Pair.cpp +38 -2
 - data/test/test_Stl_Reference_Wrapper.cpp +102 -0
 - data/test/test_Stl_SmartPointer.cpp +5 -5
 - data/test/test_Stl_Unordered_Map.cpp +697 -0
 - data/test/test_Stl_Variant.cpp +301 -0
 - data/test/test_Stl_Vector.cpp +200 -41
 - data/test/test_Struct.cpp +3 -3
 - data/test/test_To_From_Ruby.cpp +6 -0
 - data/test/test_Tracking.cpp +239 -0
 - data/test/unittest.hpp +13 -4
 - metadata +23 -13
 - data/rice/detail/Exception_Handler.hpp +0 -8
 - data/rice/detail/Exception_Handler.ipp +0 -28
 - data/rice/detail/Iterator.hpp +0 -23
 - data/rice/detail/Iterator.ipp +0 -47
 - data/rice/detail/function_traits.hpp +0 -124
 - data/rice/detail/method_data.hpp +0 -29
 - data/rice/detail/rice_traits.hpp +0 -116
 - data/rice/ruby_try_catch.hpp +0 -86
 
| 
         @@ -1,83 +1,112 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            #include <array>
         
     | 
| 
       2 
2 
     | 
    
         
             
            #include <algorithm>
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
       4 
     | 
    
         
            -
            #include "rice_traits.hpp"
         
     | 
| 
       5 
     | 
    
         
            -
            #include " 
     | 
| 
      
 4 
     | 
    
         
            +
            #include "../traits/rice_traits.hpp"
         
     | 
| 
      
 5 
     | 
    
         
            +
            #include "NativeRegistry.hpp"
         
     | 
| 
       6 
6 
     | 
    
         
             
            #include "to_ruby_defn.hpp"
         
     | 
| 
       7 
     | 
    
         
            -
            #include " 
     | 
| 
      
 7 
     | 
    
         
            +
            #include "cpp_protect.hpp"
         
     | 
| 
       8 
8 
     | 
    
         | 
| 
       9 
9 
     | 
    
         
             
            namespace Rice::detail
         
     | 
| 
       10 
10 
     | 
    
         
             
            {
         
     | 
| 
       11 
     | 
    
         
            -
              template<typename  
     | 
| 
       12 
     | 
    
         
            -
               
     | 
| 
      
 11 
     | 
    
         
            +
              template<typename Attribute_T>
         
     | 
| 
      
 12 
     | 
    
         
            +
              void NativeAttribute<Attribute_T>::define(VALUE klass, std::string name, Attribute_T attribute, AttrAccess access)
         
     | 
| 
       13 
13 
     | 
    
         
             
              {
         
     | 
| 
       14 
     | 
    
         
            -
                 
     | 
| 
      
 14 
     | 
    
         
            +
                // Create a NativeAttribute that Ruby will call to read/write C++ variables
         
     | 
| 
      
 15 
     | 
    
         
            +
                NativeAttribute_T* native = new NativeAttribute_T(klass, name, std::forward<Attribute_T>(attribute), access);
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                if (access == AttrAccess::ReadWrite || access == AttrAccess::Read)
         
     | 
| 
       15 
18 
     | 
    
         
             
                {
         
     | 
| 
       16 
     | 
    
         
            -
                   
     | 
| 
       17 
     | 
    
         
            -
                   
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
      
 19 
     | 
    
         
            +
                  // Tell Ruby to invoke the static method read to get the attribute value
         
     | 
| 
      
 20 
     | 
    
         
            +
                  detail::protect(rb_define_method, klass, name.c_str(), (RUBY_METHOD_FUNC)&NativeAttribute_T::get, 0);
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                  // Add to native registry
         
     | 
| 
      
 23 
     | 
    
         
            +
                  detail::Registries::instance.natives.add(klass, Identifier(name).id(), native);
         
     | 
| 
       19 
24 
     | 
    
         
             
                }
         
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                if (access == AttrAccess::ReadWrite || access == AttrAccess::Write)
         
     | 
| 
      
 27 
     | 
    
         
            +
                {
         
     | 
| 
      
 28 
     | 
    
         
            +
                  if (std::is_const_v<std::remove_pointer_t<T>>)
         
     | 
| 
      
 29 
     | 
    
         
            +
                  {
         
     | 
| 
      
 30 
     | 
    
         
            +
                    throw std::runtime_error(name + " is readonly");
         
     | 
| 
      
 31 
     | 
    
         
            +
                  }
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                  // Define the write method name
         
     | 
| 
      
 34 
     | 
    
         
            +
                  std::string setter = name + "=";
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                  // Tell Ruby to invoke the static method write to get the attribute value
         
     | 
| 
      
 37 
     | 
    
         
            +
                  detail::protect(rb_define_method, klass, setter.c_str(), (RUBY_METHOD_FUNC)&NativeAttribute_T::set, 1);
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                  // Add to native registry
         
     | 
| 
      
 40 
     | 
    
         
            +
                  detail::Registries::instance.natives.add(klass, Identifier(setter).id(), native);
         
     | 
| 
      
 41 
     | 
    
         
            +
                }
         
     | 
| 
      
 42 
     | 
    
         
            +
              }
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
              template<typename Attribute_T>
         
     | 
| 
      
 45 
     | 
    
         
            +
              inline VALUE NativeAttribute<Attribute_T>::get(VALUE self)
         
     | 
| 
      
 46 
     | 
    
         
            +
              {
         
     | 
| 
      
 47 
     | 
    
         
            +
                return cpp_protect([&]
         
     | 
| 
      
 48 
     | 
    
         
            +
                {
         
     | 
| 
      
 49 
     | 
    
         
            +
                  using Native_Attr_T = NativeAttribute<Attribute_T>;
         
     | 
| 
      
 50 
     | 
    
         
            +
                  Native_Attr_T* attr = detail::Registries::instance.natives.lookup<Native_Attr_T*>();
         
     | 
| 
      
 51 
     | 
    
         
            +
                  return attr->read(self);
         
     | 
| 
      
 52 
     | 
    
         
            +
                });
         
     | 
| 
       21 
53 
     | 
    
         
             
              }
         
     | 
| 
       22 
54 
     | 
    
         | 
| 
       23 
     | 
    
         
            -
              template<typename  
     | 
| 
       24 
     | 
    
         
            -
              inline VALUE NativeAttribute< 
     | 
| 
      
 55 
     | 
    
         
            +
              template<typename Attribute_T>
         
     | 
| 
      
 56 
     | 
    
         
            +
              inline VALUE NativeAttribute<Attribute_T>::set(VALUE self, VALUE value)
         
     | 
| 
       25 
57 
     | 
    
         
             
              {
         
     | 
| 
       26 
     | 
    
         
            -
                 
     | 
| 
      
 58 
     | 
    
         
            +
                return cpp_protect([&]
         
     | 
| 
       27 
59 
     | 
    
         
             
                {
         
     | 
| 
       28 
     | 
    
         
            -
                  using Native_Attr_T = NativeAttribute< 
     | 
| 
       29 
     | 
    
         
            -
                  Native_Attr_T* attr = detail:: 
     | 
| 
      
 60 
     | 
    
         
            +
                  using Native_Attr_T = NativeAttribute<Attribute_T>;
         
     | 
| 
      
 61 
     | 
    
         
            +
                  Native_Attr_T* attr = detail::Registries::instance.natives.lookup<Native_Attr_T*>();
         
     | 
| 
       30 
62 
     | 
    
         
             
                  return attr->write(self, value);
         
     | 
| 
       31 
     | 
    
         
            -
                }
         
     | 
| 
       32 
     | 
    
         
            -
                RUBY_CATCH
         
     | 
| 
      
 63 
     | 
    
         
            +
                });
         
     | 
| 
       33 
64 
     | 
    
         
             
              }
         
     | 
| 
       34 
65 
     | 
    
         | 
| 
       35 
     | 
    
         
            -
              template<typename  
     | 
| 
       36 
     | 
    
         
            -
              NativeAttribute< 
     | 
| 
       37 
     | 
    
         
            -
             
     | 
| 
      
 66 
     | 
    
         
            +
              template<typename Attribute_T>
         
     | 
| 
      
 67 
     | 
    
         
            +
              NativeAttribute<Attribute_T>::NativeAttribute(VALUE klass, std::string name,
         
     | 
| 
      
 68 
     | 
    
         
            +
                                                                         Attribute_T attribute, AttrAccess access)
         
     | 
| 
      
 69 
     | 
    
         
            +
                : klass_(klass), name_(name), attribute_(attribute), access_(access)
         
     | 
| 
       38 
70 
     | 
    
         
             
              {
         
     | 
| 
       39 
71 
     | 
    
         
             
              }
         
     | 
| 
       40 
72 
     | 
    
         | 
| 
       41 
     | 
    
         
            -
              template<typename  
     | 
| 
       42 
     | 
    
         
            -
              inline VALUE NativeAttribute< 
     | 
| 
      
 73 
     | 
    
         
            +
              template<typename Attribute_T>
         
     | 
| 
      
 74 
     | 
    
         
            +
              inline VALUE NativeAttribute<Attribute_T>::read(VALUE self)
         
     | 
| 
       43 
75 
     | 
    
         
             
              {
         
     | 
| 
       44 
     | 
    
         
            -
                using  
     | 
| 
       45 
     | 
    
         
            -
                if constexpr (std::is_member_object_pointer_v< 
     | 
| 
      
 76 
     | 
    
         
            +
                using T_Unqualified = remove_cv_recursive_t<T>;
         
     | 
| 
      
 77 
     | 
    
         
            +
                if constexpr (std::is_member_object_pointer_v<Attribute_T>)
         
     | 
| 
       46 
78 
     | 
    
         
             
                {
         
     | 
| 
       47 
     | 
    
         
            -
                   
     | 
| 
       48 
     | 
    
         
            -
                  return To_Ruby< 
     | 
| 
      
 79 
     | 
    
         
            +
                  Receiver_T* nativeSelf = From_Ruby<Receiver_T*>().convert(self);
         
     | 
| 
      
 80 
     | 
    
         
            +
                  return To_Ruby<T_Unqualified>().convert(nativeSelf->*attribute_);
         
     | 
| 
       49 
81 
     | 
    
         
             
                }
         
     | 
| 
       50 
82 
     | 
    
         
             
                else
         
     | 
| 
       51 
83 
     | 
    
         
             
                {
         
     | 
| 
       52 
     | 
    
         
            -
                  return To_Ruby< 
     | 
| 
      
 84 
     | 
    
         
            +
                  return To_Ruby<T_Unqualified>().convert(*attribute_);
         
     | 
| 
       53 
85 
     | 
    
         
             
                }
         
     | 
| 
       54 
86 
     | 
    
         
             
              }
         
     | 
| 
       55 
87 
     | 
    
         | 
| 
       56 
     | 
    
         
            -
              template<typename  
     | 
| 
       57 
     | 
    
         
            -
              inline VALUE NativeAttribute< 
     | 
| 
      
 88 
     | 
    
         
            +
              template<typename Attribute_T>
         
     | 
| 
      
 89 
     | 
    
         
            +
              inline VALUE NativeAttribute<Attribute_T>::write(VALUE self, VALUE value)
         
     | 
| 
       58 
90 
     | 
    
         
             
              {
         
     | 
| 
       59 
     | 
    
         
            -
                if constexpr ( 
     | 
| 
      
 91 
     | 
    
         
            +
                if constexpr (std::is_fundamental_v<intrinsic_type<T>> && std::is_pointer_v<T>)
         
     | 
| 
       60 
92 
     | 
    
         
             
                {
         
     | 
| 
       61 
     | 
    
         
            -
                   
     | 
| 
       62 
     | 
    
         
            -
                  nativeSelf->*attr_ = From_Ruby<Return_T>().convert(value);
         
     | 
| 
      
 93 
     | 
    
         
            +
                  static_assert(true, "An fundamental value, such as an integer, cannot be assigned to an attribute that is a pointer");
         
     | 
| 
       63 
94 
     | 
    
         
             
                }
         
     | 
| 
       64 
     | 
    
         
            -
                else if constexpr ( 
     | 
| 
      
 95 
     | 
    
         
            +
                else if constexpr (std::is_same_v<intrinsic_type<T>, std::string> && std::is_pointer_v<T>)
         
     | 
| 
       65 
96 
     | 
    
         
             
                {
         
     | 
| 
       66 
     | 
    
         
            -
                   
     | 
| 
      
 97 
     | 
    
         
            +
                  static_assert(true, "An string cannot be assigned to an attribute that is a pointer");
         
     | 
| 
      
 98 
     | 
    
         
            +
                }
         
     | 
| 
      
 99 
     | 
    
         
            +
                
         
     | 
| 
      
 100 
     | 
    
         
            +
                if constexpr (!std::is_null_pointer_v<Receiver_T>)
         
     | 
| 
      
 101 
     | 
    
         
            +
                {
         
     | 
| 
      
 102 
     | 
    
         
            +
                  Receiver_T* nativeSelf = From_Ruby<Receiver_T*>().convert(self);
         
     | 
| 
      
 103 
     | 
    
         
            +
                  nativeSelf->*attribute_ = From_Ruby<T_Unqualified>().convert(value);
         
     | 
| 
      
 104 
     | 
    
         
            +
                }
         
     | 
| 
      
 105 
     | 
    
         
            +
                else if constexpr (!std::is_const_v<std::remove_pointer_t<T>>)
         
     | 
| 
      
 106 
     | 
    
         
            +
                {
         
     | 
| 
      
 107 
     | 
    
         
            +
                  *attribute_ = From_Ruby<T_Unqualified>().convert(value);
         
     | 
| 
       67 
108 
     | 
    
         
             
                }
         
     | 
| 
       68 
     | 
    
         
            -
                return value;
         
     | 
| 
       69 
     | 
    
         
            -
              }
         
     | 
| 
       70 
     | 
    
         
            -
             
     | 
| 
       71 
     | 
    
         
            -
              template<typename T>
         
     | 
| 
       72 
     | 
    
         
            -
              auto* Make_Native_Attribute(T* attr, AttrAccess access)
         
     | 
| 
       73 
     | 
    
         
            -
              {
         
     | 
| 
       74 
     | 
    
         
            -
                return new NativeAttribute<T, T*>(attr, access);
         
     | 
| 
       75 
     | 
    
         
            -
              }
         
     | 
| 
       76 
109 
     | 
    
         | 
| 
       77 
     | 
    
         
            -
             
     | 
| 
       78 
     | 
    
         
            -
              auto* Make_Native_Attribute(T Class_T::* attr, AttrAccess access)
         
     | 
| 
       79 
     | 
    
         
            -
              {
         
     | 
| 
       80 
     | 
    
         
            -
                using Attr_T = T Class_T::*;
         
     | 
| 
       81 
     | 
    
         
            -
                return new NativeAttribute<T, Attr_T, Class_T>(attr, access);
         
     | 
| 
      
 110 
     | 
    
         
            +
                return value;
         
     | 
| 
       82 
111 
     | 
    
         
             
              }
         
     | 
| 
       83 
112 
     | 
    
         
             
            } // Rice
         
     | 
| 
         @@ -2,40 +2,86 @@ 
     | 
|
| 
       2 
2 
     | 
    
         
             
            #define Rice__detail__Native_Function__hpp_
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
       4 
4 
     | 
    
         
             
            #include "ruby.hpp"
         
     | 
| 
       5 
     | 
    
         
            -
            #include " 
     | 
| 
      
 5 
     | 
    
         
            +
            #include "ExceptionHandler_defn.hpp"
         
     | 
| 
       6 
6 
     | 
    
         
             
            #include "MethodInfo.hpp"
         
     | 
| 
       7 
     | 
    
         
            -
            #include "function_traits.hpp"
         
     | 
| 
      
 7 
     | 
    
         
            +
            #include "../traits/function_traits.hpp"
         
     | 
| 
      
 8 
     | 
    
         
            +
            #include "../traits/method_traits.hpp"
         
     | 
| 
       8 
9 
     | 
    
         
             
            #include "from_ruby.hpp"
         
     | 
| 
       9 
10 
     | 
    
         | 
| 
       10 
11 
     | 
    
         
             
            namespace Rice::detail
         
     | 
| 
       11 
12 
     | 
    
         
             
            {
         
     | 
| 
       12 
     | 
    
         
            -
               
     | 
| 
      
 13 
     | 
    
         
            +
              //! The NativeFunction class calls C++ functions/methods/lambdas on behalf of Ruby
         
     | 
| 
      
 14 
     | 
    
         
            +
              /*! The NativeFunction class is an intermediate between Ruby and C++. Every method
         
     | 
| 
      
 15 
     | 
    
         
            +
               *  defined in Rice is associated with a NativeFuntion instance that is stored in
         
     | 
| 
      
 16 
     | 
    
         
            +
               *  a unordered_map maintained by the MethodData class. The key is the Ruby class
         
     | 
| 
      
 17 
     | 
    
         
            +
               *  and method.
         
     | 
| 
      
 18 
     | 
    
         
            +
               * 
         
     | 
| 
      
 19 
     | 
    
         
            +
               *  When Ruby calls into C++ it invokes the static NativeFunction.call method. This
         
     | 
| 
      
 20 
     | 
    
         
            +
               *  method then looks up the NativeFunction instance and calls its ->() operator.
         
     | 
| 
      
 21 
     | 
    
         
            +
               *
         
     | 
| 
      
 22 
     | 
    
         
            +
               *  The instance then converts each of the arguments passed from Ruby into their
         
     | 
| 
      
 23 
     | 
    
         
            +
               *  C++ equivalents. It then retrieves the C++ object (if there is one, Ruby could
         
     | 
| 
      
 24 
     | 
    
         
            +
               *  be calling a free standing method or lambda). Then it calls the C++ method
         
     | 
| 
      
 25 
     | 
    
         
            +
               *  and gets back the result. If there is a result (so not void), it is converted
         
     | 
| 
      
 26 
     | 
    
         
            +
               *  from a C++ object to a Ruby object and returned back to Ruby.
         
     | 
| 
      
 27 
     | 
    
         
            +
               * 
         
     | 
| 
      
 28 
     | 
    
         
            +
               *  This class make heavy use of C++ Template metaprogramming to determine
         
     | 
| 
      
 29 
     | 
    
         
            +
               *  the types and parameters a method takes. It then uses that information
         
     | 
| 
      
 30 
     | 
    
         
            +
               *  to perform type conversion Ruby to C++.
         
     | 
| 
      
 31 
     | 
    
         
            +
               *   
         
     | 
| 
      
 32 
     | 
    
         
            +
               *  @tparam From_Ruby_T - The type of C++ class wrapped by Ruby. Note
         
     | 
| 
      
 33 
     | 
    
         
            +
               *    this may be different than the Class of Function_T. For example, 
         
     | 
| 
      
 34 
     | 
    
         
            +
               *    std::map has a size() method but that is actually implemented on 
         
     | 
| 
      
 35 
     | 
    
         
            +
               *    an ancestor class _Tree. Thus From_Ruby_T is std::map but 
         
     | 
| 
      
 36 
     | 
    
         
            +
               *    Function_T::Class_T is _Tree. This typename must be specified
         
     | 
| 
      
 37 
     | 
    
         
            +
               *    by the calling code.
         
     | 
| 
      
 38 
     | 
    
         
            +
               *  @tparam Function_T - A template that represents the C++ function
         
     | 
| 
      
 39 
     | 
    
         
            +
               *    to call. This typename is automatically deduced by the compiler.
         
     | 
| 
      
 40 
     | 
    
         
            +
               *  @tparam IsMethod - A boolean specifying whether the function has
         
     | 
| 
      
 41 
     | 
    
         
            +
               *    a self parameter or not. Rice differentiates these two cases by
         
     | 
| 
      
 42 
     | 
    
         
            +
               *    calling them methods (self) or functions (no self).
         
     | 
| 
      
 43 
     | 
    
         
            +
               */
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
              template<typename From_Ruby_T, typename Function_T, bool IsMethod>
         
     | 
| 
       13 
46 
     | 
    
         
             
              class NativeFunction
         
     | 
| 
       14 
47 
     | 
    
         
             
              {
         
     | 
| 
       15 
48 
     | 
    
         
             
              public:
         
     | 
| 
      
 49 
     | 
    
         
            +
                using NativeFunction_T = NativeFunction<From_Ruby_T, Function_T, IsMethod>;
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
       16 
51 
     | 
    
         
             
                // We remove const to avoid an explosion of To_Ruby specializations and Ruby doesn't
         
     | 
| 
       17 
52 
     | 
    
         
             
                // have the concept of constants anyways
         
     | 
| 
       18 
53 
     | 
    
         
             
                using Return_T = remove_cv_recursive_t<typename function_traits<Function_T>::return_type>;
         
     | 
| 
       19 
     | 
    
         
            -
                using  
     | 
| 
      
 54 
     | 
    
         
            +
                using Class_T = typename method_traits<Function_T, IsMethod>::Class_T;
         
     | 
| 
       20 
55 
     | 
    
         
             
                using Arg_Ts = typename method_traits<Function_T, IsMethod>::Arg_Ts;
         
     | 
| 
       21 
     | 
    
         
            -
                using  
     | 
| 
      
 56 
     | 
    
         
            +
                using From_Ruby_Args_Ts = typename tuple_map<From_Ruby, Arg_Ts>::type;
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                // Register function with Ruby
         
     | 
| 
      
 59 
     | 
    
         
            +
                static void define(VALUE klass, std::string method_name, Function_T function, MethodInfo* methodInfo);
         
     | 
| 
       22 
60 
     | 
    
         | 
| 
       23 
61 
     | 
    
         
             
                // Static member function that Ruby calls
         
     | 
| 
       24 
62 
     | 
    
         
             
                static VALUE call(int argc, VALUE* argv, VALUE self);
         
     | 
| 
       25 
63 
     | 
    
         | 
| 
       26 
64 
     | 
    
         
             
              public:
         
     | 
| 
       27 
     | 
    
         
            -
                 
     | 
| 
      
 65 
     | 
    
         
            +
                // Disallow creating/copying/moving
         
     | 
| 
      
 66 
     | 
    
         
            +
                NativeFunction() = delete;
         
     | 
| 
      
 67 
     | 
    
         
            +
                NativeFunction(const NativeFunction_T&) = delete;
         
     | 
| 
      
 68 
     | 
    
         
            +
                NativeFunction(NativeFunction_T&&) = delete;
         
     | 
| 
      
 69 
     | 
    
         
            +
                void operator=(const NativeFunction_T&) = delete;
         
     | 
| 
      
 70 
     | 
    
         
            +
                void operator=(NativeFunction_T&&) = delete;
         
     | 
| 
       28 
71 
     | 
    
         | 
| 
       29 
72 
     | 
    
         
             
                // Invokes the wrapped function
         
     | 
| 
       30 
73 
     | 
    
         
             
                VALUE operator()(int argc, VALUE* argv, VALUE self);
         
     | 
| 
       31 
74 
     | 
    
         | 
| 
      
 75 
     | 
    
         
            +
              protected:
         
     | 
| 
      
 76 
     | 
    
         
            +
                NativeFunction(VALUE klass, std::string method_name, Function_T function, MethodInfo* methodInfo);
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
       32 
78 
     | 
    
         
             
              private:
         
     | 
| 
       33 
79 
     | 
    
         
             
                template<typename T, std::size_t I>
         
     | 
| 
       34 
80 
     | 
    
         
             
                From_Ruby<T> createFromRuby();
         
     | 
| 
       35 
81 
     | 
    
         | 
| 
       36 
82 
     | 
    
         
             
                // Create NativeArgs which are used to convert values from Ruby to C++
         
     | 
| 
       37 
83 
     | 
    
         
             
                template<std::size_t...I>
         
     | 
| 
       38 
     | 
    
         
            -
                 
     | 
| 
      
 84 
     | 
    
         
            +
                From_Ruby_Args_Ts createFromRuby(std::index_sequence<I...>& indices);
         
     | 
| 
       39 
85 
     | 
    
         | 
| 
       40 
86 
     | 
    
         
             
                To_Ruby<Return_T> createToRuby();
         
     | 
| 
       41 
87 
     | 
    
         | 
| 
         @@ -47,20 +93,21 @@ namespace Rice::detail 
     | 
|
| 
       47 
93 
     | 
    
         
             
                Arg_Ts getNativeValues(std::vector<VALUE>& values, std::index_sequence<I...>& indices);
         
     | 
| 
       48 
94 
     | 
    
         | 
| 
       49 
95 
     | 
    
         
             
                // Figure out what self is
         
     | 
| 
       50 
     | 
    
         
            -
                 
     | 
| 
      
 96 
     | 
    
         
            +
                Class_T getReceiver(VALUE self);
         
     | 
| 
       51 
97 
     | 
    
         | 
| 
       52 
98 
     | 
    
         
             
                // Do we need to keep alive any arguments?
         
     | 
| 
       53 
99 
     | 
    
         
             
                void checkKeepAlive(VALUE self, VALUE returnValue, std::vector<VALUE>& rubyValues);
         
     | 
| 
       54 
100 
     | 
    
         | 
| 
       55 
101 
     | 
    
         
             
                // Call the underlying C++ function
         
     | 
| 
       56 
     | 
    
         
            -
                VALUE invokeNativeFunction(Arg_Ts& nativeArgs);
         
     | 
| 
       57 
     | 
    
         
            -
                VALUE invokeNativeMethod(VALUE self, Arg_Ts& nativeArgs);
         
     | 
| 
      
 102 
     | 
    
         
            +
                VALUE invokeNativeFunction(const Arg_Ts& nativeArgs);
         
     | 
| 
      
 103 
     | 
    
         
            +
                VALUE invokeNativeMethod(VALUE self, const Arg_Ts& nativeArgs);
         
     | 
| 
       58 
104 
     | 
    
         | 
| 
       59 
105 
     | 
    
         
             
              private:
         
     | 
| 
       60 
     | 
    
         
            -
                 
     | 
| 
       61 
     | 
    
         
            -
                 
     | 
| 
      
 106 
     | 
    
         
            +
                VALUE klass_;
         
     | 
| 
      
 107 
     | 
    
         
            +
                std::string method_name_;
         
     | 
| 
      
 108 
     | 
    
         
            +
                Function_T function_;
         
     | 
| 
      
 109 
     | 
    
         
            +
                From_Ruby_Args_Ts fromRubys_;
         
     | 
| 
       62 
110 
     | 
    
         
             
                To_Ruby<Return_T> toRuby_;
         
     | 
| 
       63 
     | 
    
         
            -
                std::shared_ptr<Exception_Handler> handler_;
         
     | 
| 
       64 
111 
     | 
    
         
             
                std::unique_ptr<MethodInfo> methodInfo_;
         
     | 
| 
       65 
112 
     | 
    
         
             
              };
         
     | 
| 
       66 
113 
     | 
    
         
             
            }
         
     | 
| 
         @@ -2,25 +2,43 @@ 
     | 
|
| 
       2 
2 
     | 
    
         
             
            #include <algorithm>
         
     | 
| 
       3 
3 
     | 
    
         
             
            #include <stdexcept>
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
       5 
     | 
    
         
            -
            #include " 
     | 
| 
      
 5 
     | 
    
         
            +
            #include "cpp_protect.hpp"
         
     | 
| 
       6 
6 
     | 
    
         
             
            #include "to_ruby_defn.hpp"
         
     | 
| 
       7 
     | 
    
         
            -
            #include " 
     | 
| 
      
 7 
     | 
    
         
            +
            #include "NativeRegistry.hpp"
         
     | 
| 
       8 
8 
     | 
    
         | 
| 
       9 
9 
     | 
    
         
             
            namespace Rice::detail
         
     | 
| 
       10 
10 
     | 
    
         
             
            {
         
     | 
| 
       11 
     | 
    
         
            -
              template<typename Function_T, bool IsMethod>
         
     | 
| 
       12 
     | 
    
         
            -
               
     | 
| 
      
 11 
     | 
    
         
            +
              template<typename From_Ruby_T, typename Function_T, bool IsMethod>
         
     | 
| 
      
 12 
     | 
    
         
            +
              void NativeFunction<From_Ruby_T, Function_T, IsMethod>::define(VALUE klass, std::string method_name, Function_T function, MethodInfo* methodInfo)
         
     | 
| 
       13 
13 
     | 
    
         
             
              {
         
     | 
| 
       14 
     | 
    
         
            -
                 
     | 
| 
       15 
     | 
    
         
            -
                 
     | 
| 
       16 
     | 
    
         
            -
             
     | 
| 
      
 14 
     | 
    
         
            +
                // Tell Ruby to invoke the static method call on this class
         
     | 
| 
      
 15 
     | 
    
         
            +
                detail::protect(rb_define_method, klass, method_name.c_str(), (RUBY_METHOD_FUNC)&NativeFunction_T::call, -1);
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                // Now create a NativeFunction instance and save it to the natives registry keyed on
         
     | 
| 
      
 18 
     | 
    
         
            +
                // Ruby klass and method id. There may be multiple NativeFunction instances
         
     | 
| 
      
 19 
     | 
    
         
            +
                // because the same C++ method could be mapped to multiple Ruby methods.
         
     | 
| 
      
 20 
     | 
    
         
            +
                NativeFunction_T* native = new NativeFunction_T(klass, method_name, std::forward<Function_T>(function), methodInfo);
         
     | 
| 
      
 21 
     | 
    
         
            +
                detail::Registries::instance.natives.add(klass, Identifier(method_name).id(), native);
         
     | 
| 
      
 22 
     | 
    
         
            +
              }
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
              template<typename From_Ruby_T, typename Function_T, bool IsMethod>
         
     | 
| 
      
 25 
     | 
    
         
            +
              VALUE NativeFunction<From_Ruby_T, Function_T, IsMethod>::call(int argc, VALUE* argv, VALUE self)
         
     | 
| 
      
 26 
     | 
    
         
            +
              {
         
     | 
| 
      
 27 
     | 
    
         
            +
                // Look up the native function based on the Ruby klass and method id
         
     | 
| 
      
 28 
     | 
    
         
            +
                NativeFunction_T* nativeFunction = detail::Registries::instance.natives.lookup<NativeFunction_T*>();
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                // Execute the function but make sure to catch any C++ exceptions!
         
     | 
| 
      
 31 
     | 
    
         
            +
                return cpp_protect([&]
         
     | 
| 
      
 32 
     | 
    
         
            +
                {
         
     | 
| 
      
 33 
     | 
    
         
            +
                  return nativeFunction->operator()(argc, argv, self);
         
     | 
| 
      
 34 
     | 
    
         
            +
                });
         
     | 
| 
       17 
35 
     | 
    
         
             
              }
         
     | 
| 
       18 
36 
     | 
    
         | 
| 
       19 
     | 
    
         
            -
              template<typename Function_T, bool IsMethod>
         
     | 
| 
       20 
     | 
    
         
            -
              NativeFunction<Function_T, IsMethod>::NativeFunction( 
     | 
| 
       21 
     | 
    
         
            -
                :  
     | 
| 
      
 37 
     | 
    
         
            +
              template<typename From_Ruby_T, typename Function_T, bool IsMethod>
         
     | 
| 
      
 38 
     | 
    
         
            +
              NativeFunction<From_Ruby_T, Function_T, IsMethod>::NativeFunction(VALUE klass, std::string method_name, Function_T function, MethodInfo* methodInfo)
         
     | 
| 
      
 39 
     | 
    
         
            +
                : klass_(klass), method_name_(method_name), function_(function), methodInfo_(methodInfo)
         
     | 
| 
       22 
40 
     | 
    
         
             
              {
         
     | 
| 
       23 
     | 
    
         
            -
             
     | 
| 
      
 41 
     | 
    
         
            +
               // Create a tuple of NativeArgs that will convert the Ruby values to native values. For 
         
     | 
| 
       24 
42 
     | 
    
         
             
                // builtin types NativeArgs will keep a copy of the native value so that it 
         
     | 
| 
       25 
43 
     | 
    
         
             
                // can be passed by reference or pointer to the native function. For non-builtin types
         
     | 
| 
       26 
44 
     | 
    
         
             
                // it will just pass the value through.
         
     | 
| 
         @@ -30,9 +48,9 @@ namespace Rice::detail 
     | 
|
| 
       30 
48 
     | 
    
         
             
                this->toRuby_ = this->createToRuby();
         
     | 
| 
       31 
49 
     | 
    
         
             
              }
         
     | 
| 
       32 
50 
     | 
    
         | 
| 
       33 
     | 
    
         
            -
              template<typename Function_T, bool IsMethod>
         
     | 
| 
      
 51 
     | 
    
         
            +
              template<typename From_Ruby_T, typename Function_T, bool IsMethod>
         
     | 
| 
       34 
52 
     | 
    
         
             
              template<typename T, std::size_t I>
         
     | 
| 
       35 
     | 
    
         
            -
              From_Ruby<T> NativeFunction<Function_T, IsMethod>::createFromRuby()
         
     | 
| 
      
 53 
     | 
    
         
            +
              From_Ruby<T> NativeFunction<From_Ruby_T, Function_T, IsMethod>::createFromRuby()
         
     | 
| 
       36 
54 
     | 
    
         
             
              {
         
     | 
| 
       37 
55 
     | 
    
         
             
                // Does the From_Ruby instantiation work with Arg?
         
     | 
| 
       38 
56 
     | 
    
         
             
                if constexpr (std::is_constructible_v<From_Ruby<T>, Arg*>)
         
     | 
| 
         @@ -45,8 +63,8 @@ namespace Rice::detail 
     | 
|
| 
       45 
63 
     | 
    
         
             
                }
         
     | 
| 
       46 
64 
     | 
    
         
             
              }
         
     | 
| 
       47 
65 
     | 
    
         | 
| 
       48 
     | 
    
         
            -
              template<typename Function_T, bool IsMethod>
         
     | 
| 
       49 
     | 
    
         
            -
              To_Ruby<typename NativeFunction<Function_T, IsMethod>::Return_T> NativeFunction<Function_T, IsMethod>::createToRuby()
         
     | 
| 
      
 66 
     | 
    
         
            +
              template<typename From_Ruby_T, typename Function_T, bool IsMethod>
         
     | 
| 
      
 67 
     | 
    
         
            +
              To_Ruby<typename NativeFunction<From_Ruby_T, Function_T, IsMethod>::Return_T> NativeFunction<From_Ruby_T, Function_T, IsMethod>::createToRuby()
         
     | 
| 
       50 
68 
     | 
    
         
             
              {
         
     | 
| 
       51 
69 
     | 
    
         
             
                // Does the From_Ruby instantiation work with ReturnInfo?
         
     | 
| 
       52 
70 
     | 
    
         
             
                if constexpr (std::is_constructible_v<To_Ruby<Return_T>, Return*>)
         
     | 
| 
         @@ -59,41 +77,41 @@ namespace Rice::detail 
     | 
|
| 
       59 
77 
     | 
    
         
             
                }
         
     | 
| 
       60 
78 
     | 
    
         
             
              }
         
     | 
| 
       61 
79 
     | 
    
         | 
| 
       62 
     | 
    
         
            -
              template<typename Function_T, bool IsMethod>
         
     | 
| 
      
 80 
     | 
    
         
            +
              template<typename From_Ruby_T, typename Function_T, bool IsMethod>
         
     | 
| 
       63 
81 
     | 
    
         
             
              template<std::size_t... I>
         
     | 
| 
       64 
     | 
    
         
            -
              typename NativeFunction<Function_T, IsMethod>:: 
     | 
| 
      
 82 
     | 
    
         
            +
              typename NativeFunction<From_Ruby_T, Function_T, IsMethod>::From_Ruby_Args_Ts NativeFunction<From_Ruby_T, Function_T, IsMethod>::createFromRuby(std::index_sequence<I...>& indices)
         
     | 
| 
       65 
83 
     | 
    
         
             
              {
         
     | 
| 
       66 
84 
     | 
    
         
             
                return std::make_tuple(createFromRuby<remove_cv_recursive_t<typename std::tuple_element<I, Arg_Ts>::type>, I>()...);
         
     | 
| 
       67 
85 
     | 
    
         
             
              }
         
     | 
| 
       68 
86 
     | 
    
         | 
| 
       69 
     | 
    
         
            -
              template<typename Function_T, bool IsMethod>
         
     | 
| 
       70 
     | 
    
         
            -
              std::vector<VALUE> NativeFunction<Function_T, IsMethod>::getRubyValues(int argc, VALUE* argv)
         
     | 
| 
      
 87 
     | 
    
         
            +
              template<typename From_Ruby_T, typename Function_T, bool IsMethod>
         
     | 
| 
      
 88 
     | 
    
         
            +
              std::vector<VALUE> NativeFunction<From_Ruby_T, Function_T, IsMethod>::getRubyValues(int argc, VALUE* argv)
         
     | 
| 
       71 
89 
     | 
    
         
             
              {
         
     | 
| 
       72 
     | 
    
         
            -
                // Setup a tuple  
     | 
| 
      
 90 
     | 
    
         
            +
                // Setup a tuple for the leading rb_scan_args arguments
         
     | 
| 
       73 
91 
     | 
    
         
             
                std::string scanFormat = this->methodInfo_->formatString();
         
     | 
| 
       74 
     | 
    
         
            -
                std::tuple<int, VALUE*, const char*>  
     | 
| 
      
 92 
     | 
    
         
            +
                std::tuple<int, VALUE*, const char*> rbScanArgs = std::forward_as_tuple(argc, argv, scanFormat.c_str());
         
     | 
| 
       75 
93 
     | 
    
         | 
| 
       76 
     | 
    
         
            -
                // Create a vector to store the  
     | 
| 
       77 
     | 
    
         
            -
                std::vector<VALUE>  
     | 
| 
      
 94 
     | 
    
         
            +
                // Create a vector to store the VALUEs that will be returned by rb_scan_args
         
     | 
| 
      
 95 
     | 
    
         
            +
                std::vector<VALUE> rbScanValues(std::tuple_size_v<Arg_Ts>, Qnil);
         
     | 
| 
       78 
96 
     | 
    
         | 
| 
       79 
     | 
    
         
            -
                // Convert the vector to an array so it can  
     | 
| 
       80 
     | 
    
         
            -
                 
     | 
| 
       81 
     | 
    
         
            -
                std:: 
     | 
| 
      
 97 
     | 
    
         
            +
                // Convert the vector to an array so it can be concatenated to a tuple. As importantly
         
     | 
| 
      
 98 
     | 
    
         
            +
                // fill it with pointers to rbScanValues
         
     | 
| 
      
 99 
     | 
    
         
            +
                std::array<VALUE*, std::tuple_size_v<Arg_Ts>> rbScanValuePointers;
         
     | 
| 
      
 100 
     | 
    
         
            +
                std::transform(rbScanValues.begin(), rbScanValues.end(), rbScanValuePointers.begin(),
         
     | 
| 
       82 
101 
     | 
    
         
             
                  [](VALUE& value)
         
     | 
| 
       83 
102 
     | 
    
         
             
                  {
         
     | 
| 
       84 
103 
     | 
    
         
             
                    return &value;
         
     | 
| 
       85 
104 
     | 
    
         
             
                  });
         
     | 
| 
       86 
105 
     | 
    
         | 
| 
       87 
106 
     | 
    
         
             
                // Combine the tuples and call rb_scan_args
         
     | 
| 
       88 
     | 
    
         
            -
                 
     | 
| 
       89 
     | 
    
         
            -
                std::apply(rb_scan_args, rbScanArgs);
         
     | 
| 
      
 107 
     | 
    
         
            +
                std::apply(rb_scan_args, std::tuple_cat(rbScanArgs, rbScanValuePointers));
         
     | 
| 
       90 
108 
     | 
    
         | 
| 
       91 
     | 
    
         
            -
                return  
     | 
| 
      
 109 
     | 
    
         
            +
                return rbScanValues;
         
     | 
| 
       92 
110 
     | 
    
         
             
              }
         
     | 
| 
       93 
111 
     | 
    
         | 
| 
       94 
     | 
    
         
            -
              template<typename Function_T, bool IsMethod>
         
     | 
| 
      
 112 
     | 
    
         
            +
              template<typename From_Ruby_T, typename Function_T, bool IsMethod>
         
     | 
| 
       95 
113 
     | 
    
         
             
              template<std::size_t... I>
         
     | 
| 
       96 
     | 
    
         
            -
              typename NativeFunction<Function_T, IsMethod>::Arg_Ts NativeFunction<Function_T, IsMethod>::getNativeValues(std::vector<VALUE>& values,
         
     | 
| 
      
 114 
     | 
    
         
            +
              typename NativeFunction<From_Ruby_T, Function_T, IsMethod>::Arg_Ts NativeFunction<From_Ruby_T, Function_T, IsMethod>::getNativeValues(std::vector<VALUE>& values,
         
     | 
| 
       97 
115 
     | 
    
         
             
                 std::index_sequence<I...>& indices)
         
     | 
| 
       98 
116 
     | 
    
         
             
              {
         
     | 
| 
       99 
117 
     | 
    
         
             
                // Convert each Ruby value to its native value by calling the appropriate fromRuby instance.
         
     | 
| 
         @@ -102,80 +120,91 @@ namespace Rice::detail 
     | 
|
| 
       102 
120 
     | 
    
         
             
                return std::forward_as_tuple(std::get<I>(this->fromRubys_).convert(values[I])...);
         
     | 
| 
       103 
121 
     | 
    
         
             
              }
         
     | 
| 
       104 
122 
     | 
    
         | 
| 
       105 
     | 
    
         
            -
              template<typename Function_T, bool IsMethod>
         
     | 
| 
       106 
     | 
    
         
            -
              typename NativeFunction<Function_T, IsMethod>:: 
     | 
| 
      
 123 
     | 
    
         
            +
              template<typename From_Ruby_T, typename Function_T, bool IsMethod>
         
     | 
| 
      
 124 
     | 
    
         
            +
              typename NativeFunction<From_Ruby_T, Function_T, IsMethod>::Class_T NativeFunction<From_Ruby_T, Function_T, IsMethod>::getReceiver(VALUE self)
         
     | 
| 
       107 
125 
     | 
    
         
             
              {
         
     | 
| 
       108 
126 
     | 
    
         
             
                // There is no self parameter
         
     | 
| 
       109 
     | 
    
         
            -
                if constexpr (std::is_same_v< 
     | 
| 
      
 127 
     | 
    
         
            +
                if constexpr (std::is_same_v<Class_T, std::nullptr_t>)
         
     | 
| 
       110 
128 
     | 
    
         
             
                {
         
     | 
| 
       111 
129 
     | 
    
         
             
                  return nullptr;
         
     | 
| 
       112 
130 
     | 
    
         
             
                }
         
     | 
| 
       113 
131 
     | 
    
         
             
                // Self parameter is a Ruby VALUE so no conversion is needed
         
     | 
| 
       114 
     | 
    
         
            -
                else if constexpr (std::is_same_v< 
     | 
| 
      
 132 
     | 
    
         
            +
                else if constexpr (std::is_same_v<Class_T, VALUE>)
         
     | 
| 
       115 
133 
     | 
    
         
             
                {
         
     | 
| 
       116 
134 
     | 
    
         
             
                  return self;
         
     | 
| 
       117 
135 
     | 
    
         
             
                }
         
     | 
| 
       118 
     | 
    
         
            -
                 
     | 
| 
      
 136 
     | 
    
         
            +
                /* This case happens when a class wrapped by Rice is calling a method
         
     | 
| 
      
 137 
     | 
    
         
            +
                   defined on an ancestor class. For example, the std::map size method
         
     | 
| 
      
 138 
     | 
    
         
            +
                   is defined on _Tree not map. Rice needs to know the actual type
         
     | 
| 
      
 139 
     | 
    
         
            +
                   that was wrapped so it can correctly extract the C++ object from 
         
     | 
| 
      
 140 
     | 
    
         
            +
                   the Ruby object. */
         
     | 
| 
      
 141 
     | 
    
         
            +
                else if constexpr (!std::is_same_v<intrinsic_type<Class_T>, From_Ruby_T> && 
         
     | 
| 
      
 142 
     | 
    
         
            +
                                    std::is_base_of_v<intrinsic_type<Class_T>, From_Ruby_T>)
         
     | 
| 
      
 143 
     | 
    
         
            +
                {
         
     | 
| 
      
 144 
     | 
    
         
            +
                  From_Ruby_T* instance = From_Ruby<From_Ruby_T*>().convert(self);
         
     | 
| 
      
 145 
     | 
    
         
            +
                  return dynamic_cast<Class_T>(instance);
         
     | 
| 
      
 146 
     | 
    
         
            +
                }
         
     | 
| 
      
 147 
     | 
    
         
            +
                // Self parameter could be derived from Object or it is an C++ instance and
         
     | 
| 
       119 
148 
     | 
    
         
             
                // needs to be unwrapped from Ruby
         
     | 
| 
       120 
149 
     | 
    
         
             
                else
         
     | 
| 
       121 
150 
     | 
    
         
             
                {
         
     | 
| 
       122 
     | 
    
         
            -
                  return From_Ruby< 
     | 
| 
      
 151 
     | 
    
         
            +
                  return From_Ruby<Class_T>().convert(self);
         
     | 
| 
       123 
152 
     | 
    
         
             
                }
         
     | 
| 
       124 
153 
     | 
    
         
             
              }
         
     | 
| 
       125 
154 
     | 
    
         | 
| 
       126 
     | 
    
         
            -
              template<typename Function_T, bool IsMethod>
         
     | 
| 
       127 
     | 
    
         
            -
              VALUE NativeFunction<Function_T, IsMethod>::invokeNativeFunction(Arg_Ts& nativeArgs)
         
     | 
| 
      
 155 
     | 
    
         
            +
              template<typename From_Ruby_T, typename Function_T, bool IsMethod>
         
     | 
| 
      
 156 
     | 
    
         
            +
              VALUE NativeFunction<From_Ruby_T, Function_T, IsMethod>::invokeNativeFunction(const Arg_Ts& nativeArgs)
         
     | 
| 
       128 
157 
     | 
    
         
             
              {
         
     | 
| 
       129 
158 
     | 
    
         
             
                if constexpr (std::is_void_v<Return_T>)
         
     | 
| 
       130 
159 
     | 
    
         
             
                {
         
     | 
| 
       131 
     | 
    
         
            -
                  std::apply(this-> 
     | 
| 
      
 160 
     | 
    
         
            +
                  std::apply(this->function_, nativeArgs);
         
     | 
| 
       132 
161 
     | 
    
         
             
                  return Qnil;
         
     | 
| 
       133 
162 
     | 
    
         
             
                }
         
     | 
| 
       134 
163 
     | 
    
         
             
                else
         
     | 
| 
       135 
164 
     | 
    
         
             
                {
         
     | 
| 
       136 
165 
     | 
    
         
             
                  // Call the native method and get the result
         
     | 
| 
       137 
     | 
    
         
            -
                  Return_T nativeResult = std::apply(this-> 
     | 
| 
      
 166 
     | 
    
         
            +
                  Return_T nativeResult = std::apply(this->function_, nativeArgs);
         
     | 
| 
       138 
167 
     | 
    
         | 
| 
       139 
168 
     | 
    
         
             
                  // Return the result
         
     | 
| 
       140 
169 
     | 
    
         
             
                  return this->toRuby_.convert(nativeResult);
         
     | 
| 
       141 
170 
     | 
    
         
             
                }
         
     | 
| 
       142 
171 
     | 
    
         
             
              }
         
     | 
| 
       143 
172 
     | 
    
         | 
| 
       144 
     | 
    
         
            -
              template<typename Function_T, bool IsMethod>
         
     | 
| 
       145 
     | 
    
         
            -
              VALUE NativeFunction<Function_T, IsMethod>::invokeNativeMethod(VALUE self, Arg_Ts& nativeArgs)
         
     | 
| 
      
 173 
     | 
    
         
            +
              template<typename From_Ruby_T, typename Function_T, bool IsMethod>
         
     | 
| 
      
 174 
     | 
    
         
            +
              VALUE NativeFunction<From_Ruby_T, Function_T, IsMethod>::invokeNativeMethod(VALUE self, const Arg_Ts& nativeArgs)
         
     | 
| 
       146 
175 
     | 
    
         
             
              {
         
     | 
| 
       147 
     | 
    
         
            -
                 
     | 
| 
      
 176 
     | 
    
         
            +
                Class_T receiver = this->getReceiver(self);
         
     | 
| 
       148 
177 
     | 
    
         
             
                auto selfAndNativeArgs = std::tuple_cat(std::forward_as_tuple(receiver), nativeArgs);
         
     | 
| 
       149 
178 
     | 
    
         | 
| 
       150 
179 
     | 
    
         
             
                if constexpr (std::is_void_v<Return_T>)
         
     | 
| 
       151 
180 
     | 
    
         
             
                {
         
     | 
| 
       152 
     | 
    
         
            -
                  std::apply(this-> 
     | 
| 
      
 181 
     | 
    
         
            +
                  std::apply(this->function_, selfAndNativeArgs);
         
     | 
| 
       153 
182 
     | 
    
         
             
                  return Qnil;
         
     | 
| 
       154 
183 
     | 
    
         
             
                }
         
     | 
| 
       155 
184 
     | 
    
         
             
                else
         
     | 
| 
       156 
185 
     | 
    
         
             
                {
         
     | 
| 
       157 
     | 
    
         
            -
                  Return_T nativeResult = (Return_T)std::apply(this-> 
     | 
| 
      
 186 
     | 
    
         
            +
                  Return_T nativeResult = (Return_T)std::apply(this->function_, selfAndNativeArgs);
         
     | 
| 
       158 
187 
     | 
    
         | 
| 
       159 
188 
     | 
    
         
             
                  // Special handling if the method returns self. If so we do not want
         
     | 
| 
       160 
189 
     | 
    
         
             
                  // to create a new Ruby wrapper object and instead return self.
         
     | 
| 
       161 
     | 
    
         
            -
                  if constexpr (std::is_same_v<intrinsic_type<Return_T>, intrinsic_type< 
     | 
| 
      
 190 
     | 
    
         
            +
                  if constexpr (std::is_same_v<intrinsic_type<Return_T>, intrinsic_type<Class_T>>)
         
     | 
| 
       162 
191 
     | 
    
         
             
                  {
         
     | 
| 
       163 
     | 
    
         
            -
                    if constexpr (std::is_pointer_v<Return_T> && std::is_pointer_v< 
     | 
| 
      
 192 
     | 
    
         
            +
                    if constexpr (std::is_pointer_v<Return_T> && std::is_pointer_v<Class_T>)
         
     | 
| 
       164 
193 
     | 
    
         
             
                    {
         
     | 
| 
       165 
194 
     | 
    
         
             
                      if (nativeResult == receiver)
         
     | 
| 
       166 
195 
     | 
    
         
             
                        return self;
         
     | 
| 
       167 
196 
     | 
    
         
             
                    }
         
     | 
| 
       168 
     | 
    
         
            -
                    else if constexpr (std::is_pointer_v<Return_T> && std::is_reference_v< 
     | 
| 
      
 197 
     | 
    
         
            +
                    else if constexpr (std::is_pointer_v<Return_T> && std::is_reference_v<Class_T>)
         
     | 
| 
       169 
198 
     | 
    
         
             
                    {
         
     | 
| 
       170 
199 
     | 
    
         
             
                      if (nativeResult == &receiver)
         
     | 
| 
       171 
200 
     | 
    
         
             
                        return self;
         
     | 
| 
       172 
201 
     | 
    
         
             
                    }
         
     | 
| 
       173 
     | 
    
         
            -
                    else if constexpr (std::is_reference_v<Return_T> && std::is_pointer_v< 
     | 
| 
      
 202 
     | 
    
         
            +
                    else if constexpr (std::is_reference_v<Return_T> && std::is_pointer_v<Class_T>)
         
     | 
| 
       174 
203 
     | 
    
         
             
                    {
         
     | 
| 
       175 
204 
     | 
    
         
             
                      if (&nativeResult == receiver)
         
     | 
| 
       176 
205 
     | 
    
         
             
                        return self;
         
     | 
| 
       177 
206 
     | 
    
         
             
                    }
         
     | 
| 
       178 
     | 
    
         
            -
                    else if constexpr (std::is_reference_v<Return_T> && std::is_reference_v< 
     | 
| 
      
 207 
     | 
    
         
            +
                    else if constexpr (std::is_reference_v<Return_T> && std::is_reference_v<Class_T>)
         
     | 
| 
       179 
208 
     | 
    
         
             
                    {
         
     | 
| 
       180 
209 
     | 
    
         
             
                      if (&nativeResult == &receiver)
         
     | 
| 
       181 
210 
     | 
    
         
             
                        return self;
         
     | 
| 
         @@ -186,63 +215,52 @@ namespace Rice::detail 
     | 
|
| 
       186 
215 
     | 
    
         
             
                }
         
     | 
| 
       187 
216 
     | 
    
         
             
              }
         
     | 
| 
       188 
217 
     | 
    
         | 
| 
       189 
     | 
    
         
            -
              template<typename Function_T, bool IsMethod>
         
     | 
| 
       190 
     | 
    
         
            -
              void NativeFunction<Function_T, IsMethod>::checkKeepAlive(VALUE self, VALUE returnValue, std::vector<VALUE>& rubyValues)
         
     | 
| 
      
 218 
     | 
    
         
            +
              template<typename From_Ruby_T, typename Function_T, bool IsMethod>
         
     | 
| 
      
 219 
     | 
    
         
            +
              void NativeFunction<From_Ruby_T, Function_T, IsMethod>::checkKeepAlive(VALUE self, VALUE returnValue, std::vector<VALUE>& rubyValues)
         
     | 
| 
       191 
220 
     | 
    
         
             
              {
         
     | 
| 
       192 
221 
     | 
    
         
             
                // Check function arguments
         
     | 
| 
       193 
222 
     | 
    
         
             
                Wrapper* selfWrapper = getWrapper(self);
         
     | 
| 
       194 
223 
     | 
    
         
             
                for (const Arg& arg : (*this->methodInfo_))
         
     | 
| 
       195 
224 
     | 
    
         
             
                {
         
     | 
| 
       196 
     | 
    
         
            -
                  if (arg.isKeepAlive)
         
     | 
| 
      
 225 
     | 
    
         
            +
                  if (arg.isKeepAlive())
         
     | 
| 
       197 
226 
     | 
    
         
             
                  {
         
     | 
| 
       198 
227 
     | 
    
         
             
                    selfWrapper->addKeepAlive(rubyValues[arg.position]);
         
     | 
| 
       199 
228 
     | 
    
         
             
                  }
         
     | 
| 
       200 
229 
     | 
    
         
             
                }
         
     | 
| 
       201 
230 
     | 
    
         | 
| 
       202 
231 
     | 
    
         
             
                // Check return value
         
     | 
| 
       203 
     | 
    
         
            -
                if (this->methodInfo_->returnInfo.isKeepAlive)
         
     | 
| 
      
 232 
     | 
    
         
            +
                if (this->methodInfo_->returnInfo.isKeepAlive())
         
     | 
| 
       204 
233 
     | 
    
         
             
                {
         
     | 
| 
       205 
234 
     | 
    
         
             
                  Wrapper* returnWrapper = getWrapper(returnValue);
         
     | 
| 
       206 
235 
     | 
    
         
             
                  returnWrapper->addKeepAlive(self);
         
     | 
| 
       207 
236 
     | 
    
         
             
                }
         
     | 
| 
       208 
237 
     | 
    
         
             
              }
         
     | 
| 
       209 
238 
     | 
    
         | 
| 
       210 
     | 
    
         
            -
              template<typename Function_T, bool IsMethod>
         
     | 
| 
       211 
     | 
    
         
            -
              VALUE NativeFunction<Function_T, IsMethod>::operator()(int argc, VALUE* argv, VALUE self)
         
     | 
| 
      
 239 
     | 
    
         
            +
              template<typename From_Ruby_T, typename Function_T, bool IsMethod>
         
     | 
| 
      
 240 
     | 
    
         
            +
              VALUE NativeFunction<From_Ruby_T, Function_T, IsMethod>::operator()(int argc, VALUE* argv, VALUE self)
         
     | 
| 
       212 
241 
     | 
    
         
             
              {
         
     | 
| 
       213 
     | 
    
         
            -
                 
     | 
| 
       214 
     | 
    
         
            -
                 
     | 
| 
       215 
     | 
    
         
            -
                  // Get the ruby values
         
     | 
| 
       216 
     | 
    
         
            -
                  std::vector<VALUE> rubyValues = this->getRubyValues(argc, argv);
         
     | 
| 
       217 
     | 
    
         
            -
             
     | 
| 
       218 
     | 
    
         
            -
                  auto indices = std::make_index_sequence<std::tuple_size_v<Arg_Ts>>{};
         
     | 
| 
       219 
     | 
    
         
            -
             
     | 
| 
       220 
     | 
    
         
            -
                  // Convert the Ruby values to native values
         
     | 
| 
       221 
     | 
    
         
            -
                  Arg_Ts nativeValues = this->getNativeValues(rubyValues, indices);
         
     | 
| 
      
 242 
     | 
    
         
            +
                // Get the ruby values
         
     | 
| 
      
 243 
     | 
    
         
            +
                std::vector<VALUE> rubyValues = this->getRubyValues(argc, argv);
         
     | 
| 
       222 
244 
     | 
    
         | 
| 
       223 
     | 
    
         
            -
             
     | 
| 
       224 
     | 
    
         
            -
                  VALUE result = Qnil;
         
     | 
| 
       225 
     | 
    
         
            -
                  if constexpr (std::is_same_v<Self_T, std::nullptr_t>)
         
     | 
| 
       226 
     | 
    
         
            -
                  {
         
     | 
| 
       227 
     | 
    
         
            -
                    result = this->invokeNativeFunction(nativeValues);
         
     | 
| 
       228 
     | 
    
         
            -
                  }
         
     | 
| 
       229 
     | 
    
         
            -
                  else
         
     | 
| 
       230 
     | 
    
         
            -
                  {
         
     | 
| 
       231 
     | 
    
         
            -
                    result = this->invokeNativeMethod(self, nativeValues);
         
     | 
| 
       232 
     | 
    
         
            -
                  }
         
     | 
| 
      
 245 
     | 
    
         
            +
                auto indices = std::make_index_sequence<std::tuple_size_v<Arg_Ts>>{};
         
     | 
| 
       233 
246 
     | 
    
         | 
| 
       234 
     | 
    
         
            -
             
     | 
| 
       235 
     | 
    
         
            -
             
     | 
| 
      
 247 
     | 
    
         
            +
                // Convert the Ruby values to native values
         
     | 
| 
      
 248 
     | 
    
         
            +
                Arg_Ts nativeValues = this->getNativeValues(rubyValues, indices);
         
     | 
| 
       236 
249 
     | 
    
         | 
| 
       237 
     | 
    
         
            -
             
     | 
| 
      
 250 
     | 
    
         
            +
                // Now call the native method
         
     | 
| 
      
 251 
     | 
    
         
            +
                VALUE result = Qnil;
         
     | 
| 
      
 252 
     | 
    
         
            +
                if constexpr (std::is_same_v<Class_T, std::nullptr_t>)
         
     | 
| 
      
 253 
     | 
    
         
            +
                {
         
     | 
| 
      
 254 
     | 
    
         
            +
                  result = this->invokeNativeFunction(nativeValues);
         
     | 
| 
       238 
255 
     | 
    
         
             
                }
         
     | 
| 
       239 
     | 
    
         
            -
                 
     | 
| 
      
 256 
     | 
    
         
            +
                else
         
     | 
| 
       240 
257 
     | 
    
         
             
                {
         
     | 
| 
       241 
     | 
    
         
            -
                   
     | 
| 
       242 
     | 
    
         
            -
                  {
         
     | 
| 
       243 
     | 
    
         
            -
                    return this->handler_->handle_exception();
         
     | 
| 
       244 
     | 
    
         
            -
                  }
         
     | 
| 
       245 
     | 
    
         
            -
                  RUBY_CATCH
         
     | 
| 
      
 258 
     | 
    
         
            +
                  result = this->invokeNativeMethod(self, nativeValues);
         
     | 
| 
       246 
259 
     | 
    
         
             
                }
         
     | 
| 
      
 260 
     | 
    
         
            +
             
     | 
| 
      
 261 
     | 
    
         
            +
                // Check if any function arguments or return values need to have their lifetimes tied to the receiver
         
     | 
| 
      
 262 
     | 
    
         
            +
                this->checkKeepAlive(self, result, rubyValues);
         
     | 
| 
      
 263 
     | 
    
         
            +
             
     | 
| 
      
 264 
     | 
    
         
            +
                return result;
         
     | 
| 
       247 
265 
     | 
    
         
             
              }
         
     | 
| 
       248 
266 
     | 
    
         
             
            }
         
     |