You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix!: match rosidl_buffer primitive-sequence ABI on Lyrical+ (#22)
* fix: match rosidl_buffer primitive-sequence ABI on newer distros (ros2/rosidl#942)
ros2/rosidl#942 (rosidl_buffer, from Lyrical on) adds two trailing fields to
*primitive* C sequence structs:
<T>* data; size_t size; size_t capacity; // 0 / 8 / 16
bool is_rosidl_buffer; bool owns_rosidl_buffer; // -> struct is 32 bytes
`rosidl_runtime_rs::Sequence<T>` is a single 24-byte struct for all T, so on
those distros every primitive-sequence field (float64[], uint8[], ...) is at the
wrong offset: silent corruption, or a segfault when a misread length is non-zero
(e.g. visualization_msgs/Marker::from_rmw_message, sensor_msgs/JointState,
trajectory_msgs/JointTrajectoryPoint). Message-element sequences are NOT extended
by #942, so the layout is asymmetric (primitive 32, message 24) and a plain
distro cfg on the generic struct would wrongly grow message sequences too.
Fix: a per-element `LayoutTail` on a dedicated `SequenceLayout` trait (a
supertrait of `SequenceAlloc`, so that trait stays about the C alloc functions),
carried as a trailing field on `Sequence<T>`. Primitive element types set it to
`BufferFlags` on distros that have the feature and `()` otherwise, gated on
`ros_distro` the way rclrs handles distro ABI differences; String and message
element types are always `()`.
Verified on robostack-lyrical: ROS_DISTRO=lyrical gives size_of::<Sequence<u8>>()
== 32 (matches C) and message-element Sequence == 24; ROS_DISTRO=jazzy gives 24
for both. Pairs with the rosidl_rust generator change that emits the
`SequenceLayout` impl for generated message types.
Note: `SequenceAlloc` now has `SequenceLayout` as a supertrait; hand-written
impls need a matching `SequenceLayout` impl (generated code is covered by the
generator template).
Refs ros2-rust/ros2_rust#659, ros2/rosidl#942
Assisted-by: Claude:claude-opus-5 [Claude Code]
* fix: string sequences carry the buffer flags too
rosidl_runtime_c/string.h declares String__Sequence and U16String__Sequence
through the same ROSIDL_RUNTIME_C__PRIMITIVE_SEQUENCE macro as the numeric
primitives, so from Lyrical on they carry the two trailing rosidl_buffer flags
as well. Measured on a Lyrical install: double__Sequence and String__Sequence
are both 32 bytes, while a bare String stays 24 and message element sequences
stay 24.
Leaving String, WString, BoundedString and BoundedWString on an empty
LayoutTail therefore kept every string[] field 8 bytes short, which shifts the
fields after it (for example sensor_msgs/JointState.name ahead of position,
velocity and effort). Gate their tail on the distro exactly like the primitives.
Add a layout test that compares against repr(C) mirrors of the two C shapes, so
the padding comes from the compiler rather than a hand-computed size.
Assisted-by: Claude:claude-opus-5 [Claude Code]
* test: check the layout against the installed C headers
Compile a small C file against the real headers and let it export
the sizes and offsets of the C structsas globals, then compare against
those in the tests. The expected values now come from the C compiler
reading primitives_sequence.h.
The probe sits behind the abi_check feature, which is turned on by
adding a dependency to ourselves in the dev-dependencies. This builds
cc only for test targets and a plain build doesn't pull it in.
Assisted-by: Claude:claude-opus-5 [Claude Code]
* fix: add comment that users should not use abi_check feature
* fix: pass ros_distro cfg so docs.rs shim builds can run
docs.rs has no ROS_DISTRO; build.rs must read --cfg ros_distro from rustc-args the same way rclrs does. Also document that String sequences share the primitive LayoutTail.
Assisted-by: Cursor:auto [Cursor Agent]
* fix: use env::split_paths in the ABI probe
The probe compiled under abi_check could not see Path from the cfg_if import, which broke cargo test. Match main's path-separator fix so AMENT_PREFIX_PATH works on Windows too.
Assisted-by: Cursor:auto [Cursor Agent]
* fix: give RmwMessage types an empty SequenceLayout by default
Message-element sequences stay 24 bytes on Lyrical+, so generated RMW
structs do not need a generator-emitted SequenceLayout impl. The ABI
probe now also measures a C message sequence and asserts it differs from
primitive sequences on Lyrical+.
Assisted-by: Cursor:Grok-4.6 [Cursor Agent]
---------
Co-authored-by: Mathieu David <mathieudavid@mathieudavid.org>
0 commit comments