rice 4.0.4 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +30 -0
  3. data/Rakefile +1 -1
  4. data/include/rice/rice.hpp +2596 -1771
  5. data/include/rice/stl.hpp +1580 -271
  6. data/lib/mkmf-rice.rb +5 -2
  7. data/lib/version.rb +1 -1
  8. data/rice/Arg.hpp +6 -6
  9. data/rice/Arg.ipp +8 -9
  10. data/rice/Constructor.hpp +2 -2
  11. data/rice/Data_Object.ipp +69 -15
  12. data/rice/Data_Object_defn.hpp +1 -15
  13. data/rice/Data_Type.ipp +56 -86
  14. data/rice/Data_Type_defn.hpp +14 -17
  15. data/rice/Director.hpp +0 -1
  16. data/rice/Enum.ipp +31 -22
  17. data/rice/Exception.ipp +2 -3
  18. data/rice/Exception_defn.hpp +5 -5
  19. data/rice/HandlerRegistration.hpp +15 -0
  20. data/rice/Return.hpp +5 -4
  21. data/rice/Return.ipp +8 -3
  22. data/rice/detail/ExceptionHandler.hpp +8 -0
  23. data/rice/detail/ExceptionHandler.ipp +28 -0
  24. data/rice/detail/{Exception_Handler_defn.hpp → ExceptionHandler_defn.hpp} +17 -21
  25. data/rice/detail/HandlerRegistry.hpp +51 -0
  26. data/rice/detail/HandlerRegistry.ipp +20 -0
  27. data/rice/detail/InstanceRegistry.hpp +34 -0
  28. data/rice/detail/InstanceRegistry.ipp +50 -0
  29. data/rice/detail/MethodInfo.ipp +1 -1
  30. data/rice/detail/NativeAttribute.hpp +26 -15
  31. data/rice/detail/NativeAttribute.ipp +76 -47
  32. data/rice/detail/NativeFunction.hpp +60 -13
  33. data/rice/detail/NativeFunction.ipp +103 -85
  34. data/rice/detail/NativeIterator.hpp +49 -0
  35. data/rice/detail/NativeIterator.ipp +102 -0
  36. data/rice/detail/NativeRegistry.hpp +31 -0
  37. data/rice/detail/{method_data.ipp → NativeRegistry.ipp} +20 -16
  38. data/rice/detail/Registries.hpp +26 -0
  39. data/rice/detail/Registries.ipp +23 -0
  40. data/rice/detail/RubyFunction.hpp +6 -11
  41. data/rice/detail/RubyFunction.ipp +10 -22
  42. data/rice/detail/Type.hpp +1 -1
  43. data/rice/detail/Type.ipp +2 -2
  44. data/rice/detail/TypeRegistry.hpp +8 -11
  45. data/rice/detail/TypeRegistry.ipp +3 -28
  46. data/rice/detail/Wrapper.hpp +0 -2
  47. data/rice/detail/Wrapper.ipp +73 -23
  48. data/rice/detail/cpp_protect.hpp +93 -0
  49. data/rice/detail/default_allocation_func.ipp +1 -1
  50. data/rice/detail/from_ruby.ipp +206 -2
  51. data/rice/detail/to_ruby.ipp +39 -5
  52. data/rice/detail/to_ruby_defn.hpp +1 -1
  53. data/rice/forward_declares.ipp +6 -0
  54. data/rice/global_function.hpp +0 -4
  55. data/rice/global_function.ipp +0 -6
  56. data/rice/rice.hpp +29 -24
  57. data/rice/stl.hpp +6 -1
  58. data/test/embed_ruby.cpp +0 -15
  59. data/test/test_Array.cpp +20 -24
  60. data/test/test_Class.cpp +8 -47
  61. data/test/test_Constructor.cpp +0 -2
  62. data/test/test_Data_Object.cpp +25 -11
  63. data/test/test_Data_Type.cpp +124 -28
  64. data/test/test_Director.cpp +12 -13
  65. data/test/test_Enum.cpp +65 -26
  66. data/test/test_Inheritance.cpp +9 -9
  67. data/test/test_Iterator.cpp +134 -5
  68. data/test/test_Keep_Alive.cpp +7 -7
  69. data/test/test_Memory_Management.cpp +1 -1
  70. data/test/test_Module.cpp +25 -62
  71. data/test/test_Object.cpp +66 -3
  72. data/test/test_Ownership.cpp +12 -13
  73. data/test/test_Self.cpp +12 -13
  74. data/test/test_Stl_Map.cpp +696 -0
  75. data/test/test_Stl_Optional.cpp +3 -3
  76. data/test/test_Stl_Pair.cpp +38 -2
  77. data/test/test_Stl_Reference_Wrapper.cpp +102 -0
  78. data/test/test_Stl_SmartPointer.cpp +5 -5
  79. data/test/test_Stl_Unordered_Map.cpp +697 -0
  80. data/test/test_Stl_Variant.cpp +301 -0
  81. data/test/test_Stl_Vector.cpp +200 -41
  82. data/test/test_Struct.cpp +3 -3
  83. data/test/test_To_From_Ruby.cpp +6 -0
  84. data/test/test_Tracking.cpp +239 -0
  85. data/test/unittest.hpp +13 -4
  86. metadata +23 -13
  87. data/rice/detail/Exception_Handler.hpp +0 -8
  88. data/rice/detail/Exception_Handler.ipp +0 -28
  89. data/rice/detail/Iterator.hpp +0 -23
  90. data/rice/detail/Iterator.ipp +0 -47
  91. data/rice/detail/function_traits.hpp +0 -124
  92. data/rice/detail/method_data.hpp +0 -29
  93. data/rice/detail/rice_traits.hpp +0 -116
  94. data/rice/ruby_try_catch.hpp +0 -86
@@ -1,4 +1,5 @@
1
1
  #include <memory>
2
+ #include "InstanceRegistry.hpp"
2
3
 
3
4
  namespace Rice::detail
4
5
  {
@@ -23,6 +24,11 @@ namespace Rice::detail
23
24
  {
24
25
  }
25
26
 
27
+ ~WrapperValue()
28
+ {
29
+ Registries::instance.instances.remove(this->get());
30
+ }
31
+
26
32
  void* get() override
27
33
  {
28
34
  return (void*)&this->data_;
@@ -36,8 +42,13 @@ namespace Rice::detail
36
42
  class WrapperReference : public Wrapper
37
43
  {
38
44
  public:
39
- WrapperReference(const T& data): data_(data)
45
+ WrapperReference(T& data): data_(data)
46
+ {
47
+ }
48
+
49
+ ~WrapperReference()
40
50
  {
51
+ Registries::instance.instances.remove(this->get());
41
52
  }
42
53
 
43
54
  void* get() override
@@ -46,7 +57,7 @@ namespace Rice::detail
46
57
  }
47
58
 
48
59
  private:
49
- const T& data_;
60
+ T& data_;
50
61
  };
51
62
 
52
63
  template <typename T>
@@ -59,6 +70,8 @@ namespace Rice::detail
59
70
 
60
71
  ~WrapperPointer()
61
72
  {
73
+ Registries::instance.instances.remove(this->get());
74
+
62
75
  if (this->isOwner_)
63
76
  {
64
77
  delete this->data_;
@@ -79,53 +92,76 @@ namespace Rice::detail
79
92
  template <typename T, typename Wrapper_T>
80
93
  inline VALUE wrap(VALUE klass, rb_data_type_t* rb_type, T& data, bool isOwner)
81
94
  {
95
+ VALUE result = Registries::instance.instances.lookup(&data);
96
+
97
+ if (result != Qnil)
98
+ return result;
99
+
100
+ Wrapper* wrapper = nullptr;
101
+
82
102
  if constexpr (!std::is_void_v<Wrapper_T>)
83
103
  {
84
- Wrapper_T* wrapper = new Wrapper_T(data);
85
- return TypedData_Wrap_Struct(klass, rb_type, wrapper);
104
+ wrapper = new Wrapper_T(data);
105
+ result = TypedData_Wrap_Struct(klass, rb_type, wrapper);
86
106
  }
87
107
  else if (isOwner)
88
108
  {
89
- WrapperValue<T>* wrapper = new WrapperValue<T>(data);
90
- return TypedData_Wrap_Struct(klass, rb_type, wrapper);
109
+ wrapper = new WrapperValue<T>(data);
110
+ result = TypedData_Wrap_Struct(klass, rb_type, wrapper);
91
111
  }
92
112
  else
93
113
  {
94
- WrapperReference<T>* wrapper = new WrapperReference<T>(data);
95
- return TypedData_Wrap_Struct(klass, rb_type, wrapper);
114
+ wrapper = new WrapperReference<T>(data);
115
+ result = TypedData_Wrap_Struct(klass, rb_type, wrapper);
96
116
  }
117
+
118
+ Registries::instance.instances.add(wrapper->get(), result);
119
+
120
+ return result;
97
121
  };
98
122
 
99
123
  template <typename T, typename Wrapper_T>
100
124
  inline VALUE wrap(VALUE klass, rb_data_type_t* rb_type, T* data, bool isOwner)
101
125
  {
126
+ VALUE result = Registries::instance.instances.lookup(data);
127
+
128
+ if (result != Qnil)
129
+ return result;
130
+
131
+ Wrapper* wrapper = nullptr;
132
+
102
133
  if constexpr (!std::is_void_v<Wrapper_T>)
103
134
  {
104
- Wrapper_T* wrapper = new Wrapper_T(data);
105
- return TypedData_Wrap_Struct(klass, rb_type, wrapper);
135
+ wrapper = new Wrapper_T(data);
136
+ result = TypedData_Wrap_Struct(klass, rb_type, wrapper);
106
137
  }
107
138
  else
108
139
  {
109
- WrapperPointer<T>* wrapper = new WrapperPointer<T>(data, isOwner);
110
- return TypedData_Wrap_Struct(klass, rb_type, wrapper);
140
+ wrapper = new WrapperPointer<T>(data, isOwner);
141
+ result = TypedData_Wrap_Struct(klass, rb_type, wrapper);
111
142
  }
143
+
144
+ Registries::instance.instances.add(wrapper->get(), result);
145
+ return result;
112
146
  };
113
147
 
114
148
  template <typename T>
115
149
  inline T* unwrap(VALUE value, rb_data_type_t* rb_type)
116
150
  {
117
151
  Wrapper* wrapper = getWrapper(value, rb_type);
118
- TypedData_Get_Struct(value, Wrapper, rb_type, wrapper);
119
- return static_cast<T*>(wrapper->get());
120
- }
121
152
 
122
- inline void* unwrap(VALUE value)
123
- {
124
- // Direct access to avoid any type checking
125
- Wrapper* wrapper = (Wrapper*)RTYPEDDATA_DATA(value);
126
- return wrapper->get();
127
- }
153
+ if (wrapper == nullptr)
154
+ {
155
+ std::string message = "Wrapped C++ object is nil. Did you override " +
156
+ std::string(detail::protect(rb_obj_classname, value)) +
157
+ "#initialize and forget to call super?";
128
158
 
159
+ throw std::runtime_error(message);
160
+ }
161
+
162
+ return static_cast<T*>(wrapper->get());
163
+ }
164
+
129
165
  inline Wrapper* getWrapper(VALUE value, rb_data_type_t* rb_type)
130
166
  {
131
167
  Wrapper* wrapper = nullptr;
@@ -138,14 +174,28 @@ namespace Rice::detail
138
174
  {
139
175
  WrapperPointer<T>* wrapper = nullptr;
140
176
  TypedData_Get_Struct(value, WrapperPointer<T>, rb_type, wrapper);
141
- delete wrapper;
177
+ if (wrapper)
178
+ {
179
+ Registries::instance.instances.remove(wrapper->get());
180
+ delete wrapper;
181
+ }
142
182
 
143
- wrapper = new WrapperPointer<T>(data, true);
183
+ wrapper = new WrapperPointer<T>(data, isOwner);
144
184
  RTYPEDDATA_DATA(value) = wrapper;
185
+
186
+ Registries::instance.instances.add(data, value);
145
187
  }
146
188
 
147
189
  inline Wrapper* getWrapper(VALUE value)
148
190
  {
191
+ // Turn off spurious warning on g++ 12
192
+ #ifdef __GNUC__
193
+ #pragma GCC diagnostic push
194
+ #pragma GCC diagnostic ignored "-Warray-bounds"
195
+ #endif
149
196
  return static_cast<Wrapper*>(RTYPEDDATA_DATA(value));
197
+ #ifdef __GNUC__
198
+ #pragma GCC diagnostic pop
199
+ #endif
150
200
  }
151
201
  } // namespace
@@ -0,0 +1,93 @@
1
+ #ifndef Rice__detail__cpp_protect__hpp_
2
+ #define Rice__detail__cpp_protect__hpp_
3
+
4
+ #include <regex>
5
+ #include <filesystem>
6
+ #include <stdexcept>
7
+
8
+ #include "Jump_Tag.hpp"
9
+ #include "../Exception_defn.hpp"
10
+
11
+ namespace Rice::detail
12
+ {
13
+ template <typename Callable_T>
14
+ auto cpp_protect(Callable_T&& func)
15
+ {
16
+ try
17
+ {
18
+ return func();
19
+ }
20
+ catch (...)
21
+ {
22
+ try
23
+ {
24
+ detail::Registries::instance.handlers.handler()->handle();
25
+ }
26
+ catch (::Rice::Exception const& ex)
27
+ {
28
+ rb_exc_raise(ex.value());
29
+ }
30
+ catch (::Rice::Jump_Tag const& ex)
31
+ {
32
+ rb_jump_tag(ex.tag);
33
+ }
34
+ catch (std::bad_alloc const& ex)
35
+ {
36
+ /* This won't work quite right if the rb_exc_new2 fails; not
37
+ much we can do about that, since Ruby doesn't give us access
38
+ to a pre-allocated NoMemoryError object */
39
+ rb_exc_raise(rb_exc_new2(rb_eNoMemError, ex.what()));
40
+ }
41
+ catch (std::domain_error const& ex)
42
+ {
43
+ rb_exc_raise(rb_exc_new2(rb_eFloatDomainError, ex.what()));
44
+ }
45
+ catch (std::invalid_argument const& ex)
46
+ {
47
+ rb_exc_raise(rb_exc_new2(rb_eArgError, ex.what()));
48
+ }
49
+ catch (std::filesystem::filesystem_error const& ex)
50
+ {
51
+ rb_exc_raise(rb_exc_new2(rb_eIOError, ex.what()));
52
+ }
53
+ catch (std::length_error const& ex)
54
+ {
55
+ rb_exc_raise(rb_exc_new2(rb_eRuntimeError, ex.what()));
56
+ }
57
+ catch (std::out_of_range const& ex)
58
+ {
59
+ rb_exc_raise(rb_exc_new2(rb_eRangeError, ex.what()));
60
+ }
61
+ catch (std::overflow_error const& ex)
62
+ {
63
+ rb_exc_raise(rb_exc_new2(rb_eRangeError, ex.what()));
64
+ }
65
+ catch (std::range_error const& ex)
66
+ {
67
+ rb_exc_raise(rb_exc_new2(rb_eRangeError, ex.what()));
68
+ }
69
+ catch (std::regex_error const& ex)
70
+ {
71
+ rb_exc_raise(rb_exc_new2(rb_eRegexpError, ex.what()));
72
+ }
73
+ catch (std::system_error const& ex)
74
+ {
75
+ rb_exc_raise(rb_exc_new2(rb_eSystemCallError, ex.what()));
76
+ }
77
+ catch (std::underflow_error const& ex)
78
+ {
79
+ rb_exc_raise(rb_exc_new2(rb_eRangeError, ex.what()));
80
+ }
81
+ catch (std::exception const& ex)
82
+ {
83
+ rb_exc_raise(rb_exc_new2(rb_eRuntimeError, ex.what()));
84
+ }
85
+ catch (...)
86
+ {
87
+ rb_exc_raise(rb_exc_new2(rb_eRuntimeError, "Unknown C++ exception thrown"));
88
+ }
89
+ throw std::runtime_error("Should never get here - just making compilers happy");
90
+ }
91
+ }
92
+ }
93
+ #endif // Rice__detail__cpp_protect__hpp_
@@ -7,6 +7,6 @@ namespace Rice::detail
7
7
  {
8
8
  // Create a new Ruby object but since we do not yet have a C++ object
9
9
  // just pass a nullptr. It will be set via the Constructor call
10
- return TypedData_Wrap_Struct(klass, Data_Type<T>::rb_type(), nullptr);
10
+ return TypedData_Wrap_Struct(klass, Data_Type<T>::ruby_data_type(), nullptr);
11
11
  }
12
12
  }