Skip to content

Convert serialize/deserialize to pybind11#712

Merged
sloretz merged 11 commits intomasterfrom
pybind11_serialize
Mar 18, 2021
Merged

Convert serialize/deserialize to pybind11#712
sloretz merged 11 commits intomasterfrom
pybind11_serialize

Conversation

@sloretz
Copy link
Copy Markdown
Contributor

@sloretz sloretz commented Mar 11, 2021

part of #665

@sloretz sloretz requested review from azeey and cottsay March 11, 2021 18:07
@sloretz sloretz mentioned this pull request Mar 11, 2021
34 tasks
@sloretz
Copy link
Copy Markdown
Contributor Author

sloretz commented Mar 11, 2021

CI (build: --packages-up-to rclpy test: --packages-select rclpy)

  • Linux Build Status
  • Linux-aarch64 Build Status
  • macOS Build Status
  • Windows Build Status

@sloretz sloretz force-pushed the pybind11_serialize branch from 41b3514 to ab53412 Compare March 11, 2021 18:53
@sloretz
Copy link
Copy Markdown
Contributor Author

sloretz commented Mar 11, 2021

Rebased on master

Copy link
Copy Markdown
Member

@cottsay cottsay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs some fixes for error handling.

Comment on lines +97 to +87
if (RMW_RET_OK != rmw_ret) {
throw RCLError("Failed to serialize ROS message");
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't the right way to handle RMW errors. There are explicit functions defined for it, but they're all just typedefs to rcutils error handling. It would be OK with me if you just switched this to rcutils error handling, but I think the more correct way to do it would be to introduce an RMWError exception class like you did for RCUtilsError.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fully agreed.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll update this to use RMWError from #709 once that's merged.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uses RMWError in 5204de1

Comment on lines +134 to +136
auto message_deleter = [&](void * ptr) {destroy_ros_message(ptr);};
auto deserialized_ros_msg = std::unique_ptr<void, decltype(message_deleter)>(
deserialized_ros_msg_c, message_deleter);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that in this case, you can pass destroy_ros_message directly as the deleter. Up to you.

Suggested change
auto message_deleter = [&](void * ptr) {destroy_ros_message(ptr);};
auto deserialized_ros_msg = std::unique_ptr<void, decltype(message_deleter)>(
deserialized_ros_msg_c, message_deleter);
auto deserialized_ros_msg = std::unique_ptr<void, decltype(destroy_ros_message)>(
deserialized_ros_msg_c, destroy_ros_message);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed unnecessary lambda in 801d7db

rmw_ret_t rmw_ret = rmw_deserialize(&serialized_msg, ts, deserialized_ros_msg.get());

if (RMW_RET_OK != rmw_ret) {
throw RCLError("failed to deserialize ROS message");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again with the RMW error handling.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uses RMWError in 5204de1


extern "C"
{
#include "rclpy_common/common.h"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sloretz this one's curious, why the extern "C" block? Doesn't rclpy_common/common.h include one already?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It didn't have extern "C". I added it in b51f10f

{
rcutils_ret_t ret = rmw_serialized_message_fini(&rcl_msg_);
if (RCUTILS_RET_OK != ret) {
fprintf(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sloretz FYI there's RCUTILS_SAFE_FWRITE_TO_STDERR too.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uses rcutils stderr macro in 2c8745c


/// Deserialize a ROS message
/**
* Raises RCLError on serialization failure
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sloretz nit:

Suggested change
* Raises RCLError on serialization failure
* Raises RCLError on deserialization failure

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deserialization in b174caa

/// Serialize a ROS message
/**
* Raises RCLError on serialization failure
* Raises TypeError if an argument has the wrong type
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sloretz meta: isn't this true for any Python code, native or interpreted?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm maybe it's not true in this case since the args are both py::object 😅 . It's true for any method we bind with a specific type using pybind11, so probably it can be assumed rather than documented. I removed it in 3fa151c.

}
serialized_msg.buffer_capacity = length;
serialized_msg.buffer_length = length;
serialized_msg.buffer = reinterpret_cast<uint8_t *>(serialized_buffer);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sloretz nit: why not using serialized_msg members in place instead of having these serialized_buffer and length temporary variables?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unsigned/signed conversion - speaking of which I added a check that length is greater than 0 before casting in 9efb9cc.

serialized_msg.buffer_length = length;
serialized_msg.buffer = reinterpret_cast<uint8_t *>(serialized_buffer);

destroy_ros_message_signature * destroy_ros_message = NULL;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sloretz nit:

Suggested change
destroy_ros_message_signature * destroy_ros_message = NULL;
destroy_ros_message_signature * destroy_ros_message = nullptr;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NULL -> nullptr in 0b5b9b1

}

void
init(rcutils_allocator_t allocator)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sloretz why a two-stage construction? Why not merging SerializedMessage::init with the constructor?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I had it as two-stage originally so I could reuse it in the deserialize method, but ended up not going with it to avoid a copy. I merged init and the constructor in d2d3c29


namespace rclpy
{
class SerializedMessage
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sloretz meta: perhaps a struct is more adequate?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made it a struct in 5fc0e07

}
}

rcl_serialized_message_t rcl_msg_;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sloretz meta: given it's a public member, shall we drop the trailing underscore?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't find anything in the style guide about trailing underscore's only being for private member variables, but it says structs don't have them. I converted it to a struct and removed the trailing underscore in 5fc0e07

@sloretz
Copy link
Copy Markdown
Contributor Author

sloretz commented Mar 17, 2021

CI (build: --packages-up-to rclpy test: --packages-select rclpy)

  • Linux Build Status
  • Linux-aarch64 Build Status
  • macOS Build Status
  • Windows Build Status

@sloretz sloretz requested review from cottsay and hidmic March 17, 2021 23:30
sloretz added 11 commits March 18, 2021 08:57
Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>
Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>
Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>
Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>
Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>
Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>
Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>
Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>
Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>
Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>
Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>
@sloretz sloretz force-pushed the pybind11_serialize branch from b51f10f to 787d3a6 Compare March 18, 2021 15:57
@sloretz sloretz dismissed cottsay’s stale review March 18, 2021 15:57

Feedback addressed

@sloretz
Copy link
Copy Markdown
Contributor Author

sloretz commented Mar 18, 2021

CI (build: --packages-up-to rclpy test: --packages-select rclpy)

  • Linux Build Status
  • Linux-aarch64 Build Status
  • macOS Build Status
  • Windows Build Status

@sloretz sloretz merged commit 84e467b into master Mar 18, 2021
@delete-merged-branch delete-merged-branch bot deleted the pybind11_serialize branch March 18, 2021 20:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants