Conversation
Additionally add init_and_remove_args for convenience.
wjwwood
left a comment
There was a problem hiding this comment.
lgtm overall, just some questions and suggestions
rclcpp/include/rclcpp/utilities.hpp
Outdated
| /** | ||
| * Some arguments may not have been intended as ROS arguments. This function | ||
| * populates a the aruments in a vector. Since the first argument is always assumed | ||
| * to be a process name, the vector will always contain the process name. |
There was a problem hiding this comment.
Same style comment here, one line per sentence.
rclcpp/include/rclcpp/utilities.hpp
Outdated
| */ | ||
| RCLCPP_PUBLIC | ||
| std::vector<std::string> | ||
| init_and_remove_ros_arguments(int argc, char const * const argv[]); |
There was a problem hiding this comment.
We could just change the signature of init to always return the pruned list, and users could just ignore it.
rclcpp/src/rclcpp/utilities.cpp
Outdated
| if (rcl_parse_arguments(argc, argv, alloc, &parsed_args) != RCL_RET_OK) { | ||
| std::string msg = "failed to parse arguments: "; | ||
| msg += rcl_get_error_string_safe(); | ||
| rcl_reset_error(); |
There was a problem hiding this comment.
There is a function for this:
rclcpp/rclcpp/include/rclcpp/exceptions.hpp
Lines 100 to 119 in 947e3f7
There was a problem hiding this comment.
There are other opportunities to use this below too.
rclcpp/src/rclcpp/utilities.cpp
Outdated
| rcl_allocator_t alloc = rcl_get_default_allocator(); | ||
| rcl_arguments_t parsed_args; | ||
|
|
||
| if (rcl_parse_arguments(argc, argv, alloc, &parsed_args) != RCL_RET_OK) { |
There was a problem hiding this comment.
@sloretz was there going to be a function to get the already parsed arguments?
rcl_init already does this work and keeps the rcl_arguments_t around for later use. So we could use that here. The downside is that this would need rcl_init to have been called before, which might actually be a reason to leave this as-is.
Also, we'd need to ensure the argc and argv are the same ones given to the previously called rcl_init.
So with those two caveat's maybe this is the best approach.
There was a problem hiding this comment.
@wjwwood You mean a function that gets the global parsed arguments? There is rcl_get_global_arguments. Both your caveats apply.
There was a problem hiding this comment.
Oh yeah, forgot you ended up adding that. Any opinion on how this function should work, i.e. should it reused the result of init or do it again itself to avoid the corner cases?
There was a problem hiding this comment.
As a standalone function with argc and argv passed in +1 to parsing the args again to prevent a mismatch between the arguments and the global state.
A non-public rclcpp function that made an std::vector of non-ros arguments given argc, argv, and rcl_arguments_t could be used by both remove_ros_arguments and init_and_remove_ros_arguments to avoid the double-parsing. However, inefficiency in init..() is a one-time cost in most use cases so it may not be worth the added work.
There was a problem hiding this comment.
Sounds good to me too. @mjcarroll I'll leave it up to you to either use the common function or not as @sloretz described.
There was a problem hiding this comment.
This issue would be OBE if we collapse init into a single signature that always returns a std::vector.
| msg += rcl_get_error_string_safe(); | ||
| rcl_reset_error(); | ||
| if (NULL != nonros_argv) { | ||
| alloc.deallocate(nonros_argv, alloc.state); |
There was a problem hiding this comment.
Same question as on the other pr, I would expect this to not be required. I would expect rcl_remove_ros_arguments to clean up memory allocations in an error condition, so that it is not required here.
| std::vector<std::string> return_arguments; | ||
| return_arguments.resize(nonros_argc); | ||
|
|
||
| for (int ii = 0; ii < nonros_argc; ++ii) { |
There was a problem hiding this comment.
I'd use size_t rather than int, unless you had a specific reason here.
There was a problem hiding this comment.
@wjwwood if it is size_t will windows warn about signed/unsigned comparison?
There was a problem hiding this comment.
Also MISRA, but that's not as important here.
| ASSERT_EQ(std::string{"process_name"}, args[0]); | ||
| ASSERT_EQ(std::string{"-d"}, args[1]); | ||
| ASSERT_EQ(std::string{"--foo=bar"}, args[2]); | ||
| ASSERT_EQ(std::string{"--baz"}, args[3]); |
There was a problem hiding this comment.
It would be good to see a test for init_and_remove_ros_arguments also or instead.
Also, I'd like to see tests for corner cases, like argc = 0 and/or argv = nullptr.
wjwwood
left a comment
There was a problem hiding this comment.
minor nitpick, but otherwise lgtm, I'll fix the nitpick
rclcpp/src/rclcpp/utilities.cpp
Outdated
| // See the License for the specific language governing permissions and | ||
| // limitations under the License. | ||
|
|
||
|
|
There was a problem hiding this comment.
minimize vertical whitespace: https://google.github.io/styleguide/cppguide.html#Vertical_Whitespace
| rclcpp::remove_ros_arguments(int argc, char const * const argv[]) | ||
| { | ||
| rcl_allocator_t alloc = rcl_get_default_allocator(); | ||
| rcl_arguments_t parsed_args; |
There was a problem hiding this comment.
Need to zero initialize this before calling rcl_get_zero_initialized_arguments(). This could be the source of the random segfault.
Similar to the warnings when remapping to invalid namespaces, this better communicates failures to the user. Resolves ros2#449 Signed-off-by: Jacob Perron <jacob@openrobotics.org>
Addresses rclcpp component of ros2/rcl#219
Connects to ros2/rcl#219