rice 4.8.0 → 4.9.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.
data/include/rice/stl.hpp CHANGED
@@ -2687,11 +2687,26 @@ namespace Rice
2687
2687
  Data_Type<std::shared_ptr<T>> define_shared_ptr(std::string klassName = "");
2688
2688
  }
2689
2689
 
2690
+ namespace Rice::detail
2691
+ {
2692
+ template<typename T>
2693
+ class Wrapper<std::shared_ptr<T>> : public WrapperBase
2694
+ {
2695
+ public:
2696
+ Wrapper(rb_data_type_t* rb_data_type, const std::shared_ptr<T>& data);
2697
+ ~Wrapper();
2698
+ void* get(rb_data_type_t* requestedType) override;
2699
+
2700
+ private:
2701
+ std::shared_ptr<T> data_;
2702
+ rb_data_type_t* inner_rb_data_type_;
2703
+ };
2704
+ }
2705
+
2690
2706
 
2691
2707
  // --------- shared_ptr.ipp ---------
2692
2708
  #include <memory>
2693
2709
 
2694
- // --------- Enable creation of std::shared_ptr from Ruby ---------
2695
2710
  namespace Rice
2696
2711
  {
2697
2712
  template<typename T>
@@ -2713,74 +2728,98 @@ namespace Rice
2713
2728
  }
2714
2729
 
2715
2730
  Identifier id(klassName);
2716
- Data_Type_T result = define_class_under<SharedPtr_T>(rb_mStd, id);
2731
+ Data_Type_T result = define_class_under<detail::intrinsic_type<SharedPtr_T>>(rb_mStd, id).
2732
+ define_method("get", &SharedPtr_T::get).
2733
+ define_method("swap", &SharedPtr_T::swap).
2734
+ define_method("use_count", &SharedPtr_T::use_count).
2735
+ define_method("empty?", [](SharedPtr_T& self)->bool
2736
+ {
2737
+ return !self;
2738
+ });
2717
2739
 
2718
- // std::shared_ptr<void> cannot be constructed from void* because void is incomplete
2719
- // and the deleter cannot be determined. So skip the constructor for void.
2720
- // std::shared_ptr<T[]> (array types) also skip constructor - arrays need special handling.
2721
- if constexpr (!std::is_void_v<T> && !std::is_array_v<T>)
2740
+ if constexpr (!std::is_void_v<T>)
2722
2741
  {
2723
2742
  result.define_constructor(Constructor<SharedPtr_T, typename SharedPtr_T::element_type*>(), Arg("value").takeOwnership());
2724
2743
  }
2725
2744
 
2726
- result.
2727
- define_method("get", &SharedPtr_T::get).
2728
- define_method("use_count", &SharedPtr_T::use_count).
2729
- define_method("empty?", &SharedPtr_T::operator bool);
2745
+ // Setup delegation to forward T's methods via get (only for non-fundamental, non-void types)
2746
+ if constexpr (!std::is_void_v<T> && !std::is_fundamental_v<T>)
2747
+ {
2748
+ detail::define_forwarding(result.klass(), Data_Type<T>::klass());
2749
+ }
2730
2750
 
2731
2751
  return result;
2732
2752
  }
2733
2753
  }
2734
2754
 
2735
- // --------- Type/To_Ruby/From_Ruby ---------
2755
+ // --------- Wrapper ---------
2736
2756
  namespace Rice::detail
2737
2757
  {
2738
2758
  template<typename T>
2739
- struct Type<std::shared_ptr<T>>
2759
+ Wrapper<std::shared_ptr<T>>::Wrapper(rb_data_type_t* rb_data_type, const std::shared_ptr<T>& data)
2760
+ : WrapperBase(rb_data_type), data_(data)
2740
2761
  {
2741
- static bool verify()
2762
+ using Intrinsic_T = intrinsic_type<T>;
2763
+
2764
+ if constexpr (std::is_fundamental_v<Intrinsic_T>)
2742
2765
  {
2743
- if constexpr (std::is_fundamental_v<T>)
2744
- {
2745
- Type<Pointer<T>>::verify();
2746
- Type<Buffer<T>>::verify();
2747
- }
2748
- else
2749
- {
2750
- if (!Type<intrinsic_type<T>>::verify())
2751
- {
2752
- return false;
2753
- }
2754
- }
2766
+ inner_rb_data_type_ = Data_Type<Pointer<Intrinsic_T>>::ruby_data_type();
2767
+ }
2768
+ else
2769
+ {
2770
+ inner_rb_data_type_ = Data_Type<Intrinsic_T>::ruby_data_type();
2771
+ }
2772
+ }
2755
2773
 
2756
- define_shared_ptr<T>();
2774
+ template<typename T>
2775
+ Wrapper<std::shared_ptr<T>>::~Wrapper()
2776
+ {
2777
+ Registries::instance.instances.remove(this->get(this->rb_data_type_));
2778
+ }
2757
2779
 
2758
- return true;
2780
+ template<typename T>
2781
+ void* Wrapper<std::shared_ptr<T>>::get(rb_data_type_t* requestedType)
2782
+ {
2783
+ if (rb_typeddata_inherited_p(this->rb_data_type_, requestedType))
2784
+ {
2785
+ return &this->data_;
2759
2786
  }
2760
- };
2787
+ else if (rb_typeddata_inherited_p(this->inner_rb_data_type_, requestedType))
2788
+ {
2789
+ return this->data_.get();
2790
+ }
2791
+ else
2792
+ {
2793
+ throw Exception(rb_eTypeError, "wrong argument type (expected %s)",
2794
+ requestedType->wrap_struct_name);
2795
+ }
2796
+ }
2797
+ }
2761
2798
 
2762
- // Specialization for array types std::shared_ptr<T[]>
2799
+ // --------- Type ---------
2800
+ namespace Rice::detail
2801
+ {
2763
2802
  template<typename T>
2764
- struct Type<std::shared_ptr<T[]>>
2803
+ struct Type<std::shared_ptr<T>>
2765
2804
  {
2766
2805
  static bool verify()
2767
2806
  {
2807
+ bool result = true;
2768
2808
  if constexpr (std::is_fundamental_v<T>)
2769
2809
  {
2770
- Type<Pointer<T>>::verify();
2771
- Type<Buffer<T>>::verify();
2810
+ result = result && Type<Pointer<T>>::verify();
2772
2811
  }
2773
2812
  else
2774
2813
  {
2775
- if (!Type<intrinsic_type<T>>::verify())
2776
- {
2777
- return false;
2778
- }
2814
+ result = result && Type<T>::verify();
2779
2815
  }
2780
2816
 
2781
- define_shared_ptr<T[]>();
2817
+ if (result)
2818
+ {
2819
+ define_shared_ptr<T>();
2820
+ }
2782
2821
 
2783
- return true;
2822
+ return result;
2784
2823
  }
2785
2824
  };
2786
2825
  }
@@ -3301,19 +3340,25 @@ namespace Rice::detail
3301
3340
 
3302
3341
  // ========= unique_ptr.hpp =========
3303
3342
 
3343
+ namespace Rice
3344
+ {
3345
+ template<typename T>
3346
+ Data_Type<std::unique_ptr<T>> define_unique_ptr(std::string klassName = "");
3347
+ }
3348
+
3304
3349
  namespace Rice::detail
3305
3350
  {
3306
3351
  template<typename T>
3307
3352
  class Wrapper<std::unique_ptr<T>> : public WrapperBase
3308
3353
  {
3309
3354
  public:
3310
- Wrapper(std::unique_ptr<T>&& data);
3355
+ Wrapper(rb_data_type_t* rb_data_type, std::unique_ptr<T>&& data);
3311
3356
  ~Wrapper();
3312
- void* get() override;
3313
- std::unique_ptr<T>& data();
3357
+ void* get(rb_data_type_t* requestedType) override;
3314
3358
 
3315
3359
  private:
3316
3360
  std::unique_ptr<T> data_;
3361
+ rb_data_type_t* inner_rb_data_type_;
3317
3362
  };
3318
3363
  }
3319
3364
 
@@ -3321,136 +3366,124 @@ namespace Rice::detail
3321
3366
  // --------- unique_ptr.ipp ---------
3322
3367
  #include <memory>
3323
3368
 
3324
- namespace Rice::detail
3369
+ namespace Rice
3325
3370
  {
3326
3371
  template<typename T>
3327
- inline Wrapper<std::unique_ptr<T>>::Wrapper(std::unique_ptr<T>&& data)
3328
- : data_(std::move(data))
3372
+ Data_Type<std::unique_ptr<T>> define_unique_ptr(std::string klassName)
3329
3373
  {
3330
- }
3331
-
3332
- template<typename T>
3333
- inline Wrapper<std::unique_ptr<T>>::~Wrapper()
3334
- {
3335
- Registries::instance.instances.remove(this->get());
3336
- }
3374
+ using UniquePtr_T = std::unique_ptr<T>;
3375
+ using Data_Type_T = Data_Type<UniquePtr_T>;
3337
3376
 
3338
- template<typename T>
3339
- inline void* Wrapper<std::unique_ptr<T>>::get()
3340
- {
3341
- return (void*)this->data_.get();
3342
- }
3343
-
3344
- template<typename T>
3345
- inline std::unique_ptr<T>& Wrapper<std::unique_ptr<T>>::data()
3346
- {
3347
- return data_;
3348
- }
3349
-
3350
- template <typename T>
3351
- class To_Ruby<std::unique_ptr<T>>
3352
- {
3353
- public:
3354
- To_Ruby() = default;
3355
-
3356
- explicit To_Ruby(Arg* arg) : arg_(arg)
3377
+ if (klassName.empty())
3357
3378
  {
3379
+ detail::TypeMapper<UniquePtr_T> typeMapper;
3380
+ klassName = typeMapper.rubyName();
3358
3381
  }
3359
3382
 
3360
- VALUE convert(std::unique_ptr<T>& data)
3383
+ Module rb_mStd = define_module("Std");
3384
+ if (Data_Type_T::check_defined(klassName, rb_mStd))
3361
3385
  {
3362
- std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType<T>(*data);
3363
- return detail::wrap<std::unique_ptr<T>>(rubyTypeInfo.first, rubyTypeInfo.second, data, true);
3386
+ return Data_Type_T();
3364
3387
  }
3365
3388
 
3366
- VALUE convert(std::unique_ptr<T>&& data)
3389
+ Identifier id(klassName);
3390
+ Data_Type_T result = define_class_under<detail::intrinsic_type<UniquePtr_T>>(rb_mStd, id).
3391
+ define_method("get", &UniquePtr_T::get).
3392
+ define_method("release", &UniquePtr_T::release).
3393
+ define_method("reset", &UniquePtr_T::reset).
3394
+ define_method("swap", &UniquePtr_T::swap).
3395
+ define_method("empty?", [](UniquePtr_T& self)->bool
3396
+ {
3397
+ return !self;
3398
+ });
3399
+
3400
+ // Setup delegation to forward T's methods via get (only for non-fundamental, non-void types)
3401
+ if constexpr (!std::is_void_v<T> && !std::is_fundamental_v<T>)
3367
3402
  {
3368
- std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType<T>(*data);
3369
- return detail::wrap<std::unique_ptr<T>>(rubyTypeInfo.first, rubyTypeInfo.second, data, true);
3403
+ detail::define_forwarding(result.klass(), Data_Type<T>::klass());
3370
3404
  }
3371
3405
 
3372
- private:
3373
- Arg* arg_ = nullptr;
3374
- };
3406
+ return result;
3407
+ }
3408
+ }
3375
3409
 
3376
- template <typename T>
3377
- class To_Ruby<std::unique_ptr<T>&>
3410
+ // --------- Wrapper ---------
3411
+ namespace Rice::detail
3412
+ {
3413
+ template<typename T>
3414
+ Wrapper<std::unique_ptr<T>>::Wrapper(rb_data_type_t* rb_data_type, std::unique_ptr<T>&& data)
3415
+ : WrapperBase(rb_data_type), data_(std::move(data))
3378
3416
  {
3379
- public:
3380
- To_Ruby() = default;
3417
+ using Intrinsic_T = intrinsic_type<T>;
3381
3418
 
3382
- explicit To_Ruby(Arg* arg) : arg_(arg)
3419
+ if constexpr (std::is_fundamental_v<Intrinsic_T>)
3383
3420
  {
3421
+ inner_rb_data_type_ = Data_Type<Pointer<Intrinsic_T>>::ruby_data_type();
3384
3422
  }
3385
-
3386
- VALUE convert(std::unique_ptr<T>& data)
3423
+ else
3387
3424
  {
3388
- std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType<T>(*data);
3389
- return detail::wrap<std::unique_ptr<T>>(rubyTypeInfo.first, rubyTypeInfo.second, data, true);
3425
+ inner_rb_data_type_ = Data_Type<Intrinsic_T>::ruby_data_type();
3390
3426
  }
3427
+ }
3391
3428
 
3392
- private:
3393
- Arg* arg_ = nullptr;
3394
- };
3429
+ template<typename T>
3430
+ Wrapper<std::unique_ptr<T>>::~Wrapper()
3431
+ {
3432
+ Registries::instance.instances.remove(this->get(this->rb_data_type_));
3433
+ }
3395
3434
 
3396
- template <typename T>
3397
- class From_Ruby<std::unique_ptr<T>>
3435
+ template<typename T>
3436
+ void* Wrapper<std::unique_ptr<T>>::get(rb_data_type_t* requestedType)
3398
3437
  {
3399
- public:
3400
- Wrapper<std::unique_ptr<T>>* is_same_smart_ptr(VALUE value)
3438
+ if (rb_typeddata_inherited_p(this->rb_data_type_, requestedType))
3401
3439
  {
3402
- WrapperBase* wrapper = detail::getWrapper(value, Data_Type<T>::ruby_data_type());
3403
- return dynamic_cast<Wrapper<std::unique_ptr<T>>*>(wrapper);
3440
+ return &this->data_;
3404
3441
  }
3405
-
3406
- From_Ruby() = default;
3407
-
3408
- explicit From_Ruby(Arg* arg) : arg_(arg)
3442
+ else if (rb_typeddata_inherited_p(this->inner_rb_data_type_, requestedType))
3409
3443
  {
3444
+ return this->data_.get();
3410
3445
  }
3446
+ else
3447
+ {
3448
+ throw Exception(rb_eTypeError, "wrong argument type (expected %s)",
3449
+ requestedType->wrap_struct_name);
3450
+ }
3451
+ }
3411
3452
 
3412
- double is_convertible(VALUE value)
3453
+ }
3454
+
3455
+ // --------- Type ---------
3456
+ namespace Rice::detail
3457
+ {
3458
+ template<typename T>
3459
+ struct Type<std::unique_ptr<T>>
3460
+ {
3461
+ static bool verify()
3413
3462
  {
3414
- if (!is_same_smart_ptr(value))
3463
+ bool result = true;
3464
+ if constexpr (std::is_fundamental_v<T>)
3415
3465
  {
3416
- return Convertible::None;
3466
+ result = result && Type<Pointer<T>>::verify();
3417
3467
  }
3418
-
3419
- switch (rb_type(value))
3468
+ else
3420
3469
  {
3421
- case RUBY_T_DATA:
3422
- return Convertible::Exact;
3423
- break;
3424
- default:
3425
- return Convertible::None;
3470
+ result = result && Type<T>::verify();
3426
3471
  }
3427
- }
3428
3472
 
3429
- std::unique_ptr<T> convert(VALUE value)
3430
- {
3431
- Wrapper<std::unique_ptr<T>>* wrapper = is_same_smart_ptr(value);
3432
- if (!wrapper)
3473
+ if (result)
3433
3474
  {
3434
- std::string message = "Invalid smart pointer wrapper";
3435
- throw std::runtime_error(message.c_str());
3475
+ define_unique_ptr<T>();
3436
3476
  }
3437
- return std::move(wrapper->data());
3438
- }
3439
3477
 
3440
- private:
3441
- Arg* arg_ = nullptr;
3478
+ return result;
3479
+ }
3442
3480
  };
3443
3481
 
3482
+ // --------- From_Ruby ---------
3444
3483
  template <typename T>
3445
- class From_Ruby<std::unique_ptr<T>&>
3484
+ class From_Ruby<std::unique_ptr<T>>
3446
3485
  {
3447
3486
  public:
3448
- Wrapper<std::unique_ptr<T>>* is_same_smart_ptr(VALUE value)
3449
- {
3450
- WrapperBase* wrapper = detail::getWrapper(value, Data_Type<T>::ruby_data_type());
3451
- return dynamic_cast<Wrapper<std::unique_ptr<T>>*>(wrapper);
3452
- }
3453
-
3454
3487
  From_Ruby() = default;
3455
3488
 
3456
3489
  explicit From_Ruby(Arg* arg) : arg_(arg)
@@ -3459,11 +3492,6 @@ namespace Rice::detail
3459
3492
 
3460
3493
  double is_convertible(VALUE value)
3461
3494
  {
3462
- if (!is_same_smart_ptr(value))
3463
- {
3464
- return Convertible::None;
3465
- }
3466
-
3467
3495
  switch (rb_type(value))
3468
3496
  {
3469
3497
  case RUBY_T_DATA:
@@ -3474,43 +3502,16 @@ namespace Rice::detail
3474
3502
  }
3475
3503
  }
3476
3504
 
3477
- std::unique_ptr<T>& convert(VALUE value)
3505
+ std::unique_ptr<T> convert(VALUE value)
3478
3506
  {
3479
- Wrapper<std::unique_ptr<T>>* wrapper = is_same_smart_ptr(value);
3480
- if (!wrapper)
3481
- {
3482
- std::string message = "Invalid smart pointer wrapper";
3483
- throw std::runtime_error(message.c_str());
3484
- }
3485
- return wrapper->data();
3507
+ std::unique_ptr<T>* result = detail::unwrap<std::unique_ptr<T>>(value, Data_Type<std::unique_ptr<T>>::ruby_data_type(), this->arg_ && this->arg_->isOwner());
3508
+ // The reason we need this overriden From_Ruby is to do this std::move.
3509
+ return std::move(*result);
3486
3510
  }
3487
3511
 
3488
3512
  private:
3489
3513
  Arg* arg_ = nullptr;
3490
3514
  };
3491
-
3492
- template<typename T>
3493
- struct Type<std::unique_ptr<T>>
3494
- {
3495
- static bool verify()
3496
- {
3497
- if constexpr (std::is_fundamental_v<T>)
3498
- {
3499
- return Type<Pointer<T>>::verify();
3500
- return Type<Buffer<T>>::verify();
3501
- }
3502
- else
3503
- {
3504
- return Type<T>::verify();
3505
- }
3506
- }
3507
-
3508
- static VALUE rubyKlass()
3509
- {
3510
- TypeMapper<T> typeMapper;
3511
- return typeMapper.rubyKlass();
3512
- }
3513
- };
3514
3515
  }
3515
3516
 
3516
3517
 
data/lib/rice/doc/rice.rb CHANGED
@@ -5,7 +5,8 @@ module Rice
5
5
 
6
6
  CLASS_DOCS = {
7
7
  /^Rice::Buffer/ => "ruby_api/buffer",
8
- /^Rice::Pointer/ => "ruby_api/pointer"
8
+ /^Rice::Pointer/ => "ruby_api/pointer",
9
+ /^Rice::Reference/ => "ruby_api/reference"
9
10
  }
10
11
 
11
12
  def class_url(klass)
@@ -1,21 +1,16 @@
1
1
  module Rice
2
2
  class NativeRegistry
3
3
  def native_attributes(klass)
4
- self.native_by_kind(klass, [Rice::NativeKind::AttributeReader, Rice::NativeKind::AttributeWriter])
4
+ self.lookup_by_kind(klass, Rice::NativeKind::AttributeReader) +
5
+ self.lookup_by_kind(klass, Rice::NativeKind::AttributeWriter)
5
6
  end
6
7
 
7
8
  def native_methods(klass)
8
- self.native_by_kind(klass, [Rice::NativeKind::Method])
9
+ self.lookup_by_kind(klass, Rice::NativeKind::Method)
9
10
  end
10
11
 
11
12
  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
13
+ self.lookup_by_kind(klass, Rice::NativeKind::Function)
19
14
  end
20
15
  end
21
16
  end
data/lib/rice/rbs.rb CHANGED
@@ -12,7 +12,11 @@ module Rice
12
12
 
13
13
  def generate
14
14
  STDOUT << "Writing rbs files to #{@output}" << "\n"
15
+
16
+ # Add the extension directory the path in case it ships with extra libraries
17
+ ENV["PATH"] = "#{File.dirname(self.extension)}#{File::PATH_SEPARATOR}#{ENV["PATH"]}"
15
18
  require self.extension
19
+
16
20
  types = Registries.instance.types
17
21
  types.klasses.each do |klass|
18
22
  process_class(klass)
@@ -20,10 +24,6 @@ module Rice
20
24
  end
21
25
 
22
26
  def process_class(klass)
23
- if ['Rice', 'Std'].include?(klass.name.split('::').first)
24
- return
25
- end
26
-
27
27
  STDOUT << " " << klass << "\n"
28
28
 
29
29
  native_attributes = Registries.instance.natives.native_attributes(klass).sort.group_by(&:name)
data/lib/rice/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Rice
2
- VERSION = "4.8.0"
2
+ VERSION = "4.9.0"
3
3
  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
 
@@ -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_