|
1 | 1 | # Migration |
2 | 2 |
|
| 3 | +## Version 4.10 to 4.11 |
| 4 | + |
| 5 | +Version 4.11 introduces several breaking changes in instance tracking and the C++ API wrappers. |
| 6 | + |
| 7 | +### InstanceRegistry setting changed from boolean to mode enum |
| 8 | + |
| 9 | +`InstanceRegistry.isEnabled` no longer takes/returns a boolean-style state. It now uses a mode enum: |
| 10 | +`Off`, `Owned`, `All`. |
| 11 | + |
| 12 | +Before: |
| 13 | + |
| 14 | +```ruby |
| 15 | +Rice::InstanceRegistry.isEnabled = true |
| 16 | +Rice::InstanceRegistry.isEnabled = false |
| 17 | +``` |
| 18 | + |
| 19 | +After: |
| 20 | + |
| 21 | +```ruby |
| 22 | +Rice::InstanceRegistry.isEnabled = Rice::InstanceRegistry::Owned |
| 23 | +Rice::InstanceRegistry.isEnabled = Rice::InstanceRegistry::Off |
| 24 | +Rice::InstanceRegistry.isEnabled = Rice::InstanceRegistry::All |
| 25 | +``` |
| 26 | + |
| 27 | +Also note the default changed from disabled to `Owned`. If your code depended on registry-off behavior, set it explicitly to `Off`. |
| 28 | + |
| 29 | +### `Object()` now defaults to `Qnil` (not `rb_cObject`) |
| 30 | + |
| 31 | +Default-constructed wrappers are now nil wrappers. |
| 32 | + |
| 33 | +Before: |
| 34 | + |
| 35 | +```cpp |
| 36 | +Object obj; |
| 37 | +obj.call("some_method"); // could accidentally target rb_cObject |
| 38 | +``` |
| 39 | + |
| 40 | +After: |
| 41 | + |
| 42 | +```cpp |
| 43 | +Object obj; |
| 44 | +if (!obj.is_nil()) |
| 45 | +{ |
| 46 | + obj.call("some_method"); |
| 47 | +} |
| 48 | +``` |
| 49 | + |
| 50 | +Or initialize explicitly: |
| 51 | + |
| 52 | +```cpp |
| 53 | +Object obj(rb_cObject); |
| 54 | +obj.call("some_method"); |
| 55 | +``` |
| 56 | +
|
| 57 | +### `Object::test()` removed |
| 58 | +
|
| 59 | +Replace calls to `test()` with either `operator bool()` or `is_nil()`, depending on intent. |
| 60 | +
|
| 61 | +Before: |
| 62 | +
|
| 63 | +```cpp |
| 64 | +if (obj.test()) |
| 65 | +{ |
| 66 | + // truthy |
| 67 | +} |
| 68 | +``` |
| 69 | + |
| 70 | +After: |
| 71 | + |
| 72 | +```cpp |
| 73 | +if (obj) |
| 74 | +{ |
| 75 | + // truthy |
| 76 | +} |
| 77 | +``` |
| 78 | + |
| 79 | +Or, if you specifically need nil checks: |
| 80 | + |
| 81 | +```cpp |
| 82 | +if (obj.is_nil()) |
| 83 | +{ |
| 84 | + // nil |
| 85 | +} |
| 86 | +``` |
| 87 | + |
| 88 | +### Global `Object` constants removed |
| 89 | + |
| 90 | +The convenience globals were removed: |
| 91 | +`Rice::Nil`, `Rice::True`, `Rice::False`, `Rice::Undef`. |
| 92 | + |
| 93 | +Before: |
| 94 | + |
| 95 | +```cpp |
| 96 | +Object value = Rice::Nil; |
| 97 | +``` |
| 98 | + |
| 99 | +After: |
| 100 | + |
| 101 | +```cpp |
| 102 | +Object value(Qnil); |
| 103 | +Object truthy(Qtrue); |
| 104 | +Object falsy(Qfalse); |
| 105 | +Object undef_value(Qundef); |
| 106 | +``` |
| 107 | +
|
| 108 | +### C++ API wrappers now use `Pin` internally |
| 109 | +
|
| 110 | +Wrapper classes (such as `Object`) now pin their wrapped Ruby value internally for GC safety. |
| 111 | +
|
| 112 | +Most users do not need code changes for this update. The primary behavior change is improved safety for long-lived wrappers, including wrappers stored in containers: |
| 113 | +
|
| 114 | +```cpp |
| 115 | +std::vector<Object> values; |
| 116 | +values.push_back(Object(rb_str_new_cstr("hello"))); |
| 117 | +``` |
| 118 | + |
| 119 | +If you previously added ad-hoc GC guards only to protect wrapper objects, those guards may no longer be necessary for the wrappers themselves. |
| 120 | + |
| 121 | +## Version 4.7 to 4.10 |
| 122 | + |
| 123 | +Versions 4.8, 4.9, and 4.10 introduced several incompatible C++ API changes. |
| 124 | + |
| 125 | +### Buffer/GVL API renames (4.8) |
| 126 | + |
| 127 | +Before: |
| 128 | + |
| 129 | +```cpp |
| 130 | +define_method("read", &MyClass::read, Arg("buffer").isBuffer()); |
| 131 | +define_method("write", &MyClass::write, Return().isBuffer()); |
| 132 | +define_method("compute", &MyClass::compute, Function().noGVL()); |
| 133 | +``` |
| 134 | +
|
| 135 | +After: |
| 136 | +
|
| 137 | +```cpp |
| 138 | +define_method("read", &MyClass::read, ArgBuffer("buffer")); |
| 139 | +define_method("write", &MyClass::write, ReturnBuffer()); |
| 140 | +define_method("compute", &MyClass::compute, NoGvL()); |
| 141 | +``` |
| 142 | + |
| 143 | +### `is_convertible` return type changed (4.8) |
| 144 | + |
| 145 | +`From_Ruby<T>::is_convertible` must return `double` instead of `Convertible`. |
| 146 | + |
| 147 | +Before: |
| 148 | + |
| 149 | +```cpp |
| 150 | +Convertible is_convertible(VALUE value) |
| 151 | +{ |
| 152 | + return Convertible::Exact; |
| 153 | +} |
| 154 | +``` |
| 155 | +
|
| 156 | +After: |
| 157 | +
|
| 158 | +```cpp |
| 159 | +double is_convertible(VALUE value) |
| 160 | +{ |
| 161 | + return Convertible::Exact; |
| 162 | +} |
| 163 | +``` |
| 164 | + |
| 165 | +### Method/default argument verification is stricter (4.8) |
| 166 | + |
| 167 | +Rice now validates default arguments and type registrations more aggressively. Code that previously compiled but had mismatched/default argument types may now raise errors during binding setup. |
| 168 | + |
| 169 | +Migration step: |
| 170 | +1. Ensure every default argument value matches the bound C++ parameter type. |
| 171 | +2. Ensure all custom/opaque types are registered before using them in defaults. |
| 172 | + |
| 173 | +### Smart pointer wrapper internals changed (4.9) |
| 174 | + |
| 175 | +If you implemented custom Rice-side smart pointer wrappers, update them to the current `Std::SharedPtr<T>` / `Std::UniquePtr<T>` model and forwarding behavior. |
| 176 | + |
| 177 | +Most users who only consume smart pointers through `define_method`/`define_constructor` do not need code changes. |
| 178 | + |
| 179 | +### `Address_Registration_Guard` replaced by `Pin` (4.10) |
| 180 | + |
| 181 | +Before: |
| 182 | + |
| 183 | +```cpp |
| 184 | +VALUE value_; |
| 185 | +Address_Registration_Guard guard_; |
| 186 | + |
| 187 | +MyClass() |
| 188 | + : value_(rb_str_new2("test")), guard_(&value_) |
| 189 | +{ |
| 190 | +} |
| 191 | +``` |
| 192 | +
|
| 193 | +After: |
| 194 | +
|
| 195 | +```cpp |
| 196 | +Pin pin_; |
| 197 | +
|
| 198 | +MyClass() |
| 199 | + : pin_(rb_str_new2("test")) |
| 200 | +{ |
| 201 | +} |
| 202 | +
|
| 203 | +VALUE value() const |
| 204 | +{ |
| 205 | + return pin_.value(); |
| 206 | +} |
| 207 | +``` |
| 208 | + |
| 209 | +### Blocks are converted to Procs in C++ bindings (4.10) |
| 210 | + |
| 211 | +If your C++ method expects a Ruby block, explicitly receive it as a `VALUE`/`Object` parameter and mark it as a value arg. |
| 212 | + |
| 213 | +Before: |
| 214 | + |
| 215 | +```cpp |
| 216 | +define_method("run_with_block", [](VALUE self) |
| 217 | +{ |
| 218 | + // expected implicit block handling |
| 219 | +}); |
| 220 | +``` |
| 221 | +
|
| 222 | +After: |
| 223 | +
|
| 224 | +```cpp |
| 225 | +define_method("run_with_block", [](VALUE self, VALUE proc) |
| 226 | +{ |
| 227 | + // proc is the Ruby block converted to Proc |
| 228 | +}, Arg("proc").setValue()); |
| 229 | +``` |
| 230 | + |
| 231 | +### `Data_Type<T>::define()` removed (4.10) |
| 232 | + |
| 233 | +Use class template binding helpers / explicit factory functions instead of `Data_Type<T>::define()`. |
| 234 | + |
| 235 | +Migration step: |
| 236 | +1. Remove `Data_Type<T>::define()` calls. |
| 237 | +2. Replace with `define_class`/`define_class_under` flows documented in [Class Templates](bindings/class_templates.md). |
| 238 | + |
3 | 239 | ## Version 4.6 to 4.7 |
4 | 240 |
|
5 | 241 | Version 4.7 has a couple of breaking changes. |
|
0 commit comments