Add support for rosidl::Buffer in rosidl Python path for rclpy#250
Add support for rosidl::Buffer in rosidl Python path for rclpy#250
Conversation
Signed-off-by: CY Chen <cyc@nvidia.com>
hidmic
left a comment
There was a problem hiding this comment.
First pass. Ownership is bit fuzzy.
| Py_DECREF(backend_attr); | ||
| Py_DECREF(field); | ||
| // Sentinel is set, skip normal conversion for this field | ||
| goto @(member.name)__done; |
There was a problem hiding this comment.
@nvcyc why not simply return true? Is this missing some cleanup?
There was a problem hiding this comment.
Returning here would skip iterating through the rest of the members in the same message, so we need goto @(member.name)__done; to make sure that it goes to the next member within the loop starting at:
There was a problem hiding this comment.
Ah, I missed EmPy's end for statement. Thanks for the clarification
| @(bi) if (length > 0) { | ||
| @(bi) PyObject * pop = PyObject_GetAttrString(field, "pop"); | ||
| @(bi) assert(pop != NULL); | ||
| @(bi) for (Py_ssize_t i = 0; i < length; ++i) { |
There was a problem hiding this comment.
@nvcyc meta: I know this code predates your implementation but wow. I can see looping over pop instead of clear having a massive impact in runtime performance.
There was a problem hiding this comment.
Agreed. We can replace this part with either
PyObject * ret = PyObject_CallMethodNoArgs(field, "clear");but this only works with Python 3.13 or higher (reference)PySequence_DelSlice(field, 0, length)that should work in any Python version
Signed-off-by: CY Chen <cyc@nvidia.com>
Signed-off-by: CY Chen <cyc@nvidia.com>
Description
This pull request adds
rosidl::Buffersupport for uint8[] fields in the Python code generation path.This pull request consists of the following key changes:
_msg.py.em): Foruint8[]fields, the generated setters now allow assigning fromrosidl_buffer.Bufferor plainarray.array. Existing code that setsmsg.data = array.array('B', ...)continues to work unchanged._msg_support.c.em): Messages withuint8[]fields use the sequence'sis_rosidl_bufferflag to determine the conversion path:rosidl_buffer.Bufferobjects, calls_get_buffer_ptr()and sets the C++ Buffer pointer plusis_rosidl_buffer = trueso the RMW path uses the existing buffer without copying. Forarray.arrayobjects, uses the normal byte-copy path.is_rosidl_buffer == true), calls_take_buffer_from_ptr()to wrap the pointer in a PythonBuffer(taking ownership) and set it on the message. CPU-based data is converted toarray.arrayas before.Is this user-facing behavior change?
This pull request does not change existing rclpy behavior. Existing code using
array.arrayforuint8[]fields continues to work. Therosidl_buffer.Buffertype is only encountered when a subscriber receives data from a non-CPU buffer backend (and has opted in viaacceptable_buffer_backends).Did you use Generative AI?
Yes. Claude (claude-4.6-opus) via Cursor was used to assist with creating an initial prototype version of the changes contained in this PR.
Additional Information
This PR is part of the broader ROS 2 native buffer feature introduced in this post.