Sha256: 7a0c6c62c307e73711721bac38bc13e3f2cd584b623774b69089d8c5f16af131

Contents?: true

Size: 1.49 KB

Versions: 5

Compression:

Stored size: 1.49 KB

Contents

// Ruby 2.7 now includes a similarly named macro that uses templates to
// pick the right overload for the underlying function. That doesn't work
// for our cases because we are using this method dynamically and get a
// compilation error otherwise. This removes the macro and lets us fall
// back to the C-API underneath again.
#undef rb_define_method_id

namespace Rice::detail
{
  // Effective Java (2nd edition)
  // https://stackoverflow.com/a/2634715
  inline size_t MethodData::key(VALUE klass, ID id)
  {
    if (rb_type(klass) == T_ICLASS)
    {
      klass = detail::protect(rb_class_of, klass);
    }

    uint32_t prime = 53;
    return (prime + klass) * prime + id;
  }

  template <typename Return_T>
  inline Return_T MethodData::data()
  {
    ID id;
    VALUE klass;
    if (!rb_frame_method_id_and_class(&id, &klass))
    {
      rb_raise(rb_eRuntimeError, "Cannot get method id and class for function");
    }

    auto iter = methodWrappers_.find(key(klass, id));
    if (iter == methodWrappers_.end())
    {
      rb_raise(rb_eRuntimeError, "Could not find data for klass and method id");
    }

    std::any data = iter->second;
    return std::any_cast<Return_T>(data);
  }

  template<typename Function_T>
  inline void MethodData::define_method(VALUE klass, ID id, Function_T func, int arity, std::any data)
  {
    // Define the method
    protect(rb_define_method_id, klass, id, (RUBY_METHOD_FUNC)func, arity);

    // Now store data about it
    methodWrappers_[key(klass, id)] = data;
  }
}

Version data entries

5 entries across 5 versions & 1 rubygems

Version Path
rice-4.0.4 rice/detail/method_data.ipp
rice-4.0.3 rice/detail/method_data.ipp
rice-4.0.2 rice/detail/method_data.ipp
rice-4.0.1 rice/detail/method_data.ipp
rice-4.0.0 rice/detail/method_data.ipp