Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Providing logging macro signature that accepts std::string #573

Merged
merged 6 commits into from
Oct 25, 2018
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions rclcpp/include/rclcpp/utilities.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,27 @@ sub_will_underflow(const T x, const T y)
return (y > 0) && (x < (std::numeric_limits<T>::min() + y));
}

/// Return the same string.
/**
* This function is overloaded to transform any string to C-style string
*
* \param[in] string_in is the string to be returned
* \return The same string.
*/
RCLCPP_PUBLIC
const char *
get_c_string(const char * string_in);

/// Return the string, converted to C string
/**
*
* \param[in] string_in is a std::string
* \return The string tranformed to C string.
Copy link
Member

Choose a reason for hiding this comment

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

Spelling: tranformed

Copy link
Contributor Author

Choose a reason for hiding this comment

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

uhhh, it is true. Sorry :S

Fixed

*/
RCLCPP_PUBLIC
const char *
Copy link
Member

Choose a reason for hiding this comment

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

I think you just need RCLCPP_PUBLIC on each of these functions.

Copy link
Contributor Author

@fmrico fmrico Oct 24, 2018

Choose a reason for hiding this comment

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

Added RCLCPP_PUBLIC to get_c_string functions. I didn't know that it was necessary for Windows. I use only Linux :S . I hope it works with these changes.

I also documented both functions and macros.

get_c_string(const std::string & string_in);

} // namespace rclcpp

#endif // RCLCPP__UTILITIES_HPP_
10 changes: 8 additions & 2 deletions rclcpp/resource/logging.hpp.em
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

#include "rclcpp/logger.hpp"
#include "rcutils/logging_macros.h"
#include "rclcpp/utilities.hpp"

// These are used for compiling out logging macros lower than a minimum severity.
#define RCLCPP_LOG_MIN_SEVERITY_DEBUG 0
Expand All @@ -30,6 +31,9 @@
#define RCLCPP_LOG_MIN_SEVERITY_FATAL 4
#define RCLCPP_LOG_MIN_SEVERITY_NONE 5

#define RCLCPP_FIRST_ARG(N, ...) N
#define RCLCPP_ALL_BUT_FIRST_ARGS(N, ...) , ##__VA_ARGS__

/**
* \def RCLCPP_LOG_MIN_SEVERITY
* Define RCLCPP_LOG_MIN_SEVERITY=RCLCPP_LOG_MIN_SEVERITY_[DEBUG|INFO|WARN|ERROR|FATAL]
Expand Down Expand Up @@ -82,7 +86,8 @@ def is_supported_feature_combination(feature_combination):
@[ for param_name, doc_line in feature_combinations[feature_combination].params.items()]@
* \param @(param_name) @(doc_line)
@[ end for]@
* \param ... The format string, followed by the variable arguments for the format string
* \param ... The format string, followed by the variable arguments for the format string.
* It also accepts a single argument of type std::string.
*/
#define RCLCPP_@(severity)@(suffix)(logger, @(''.join([p + ', ' for p in get_macro_parameters(feature_combination).keys()]))...) \
static_assert( \
Expand All @@ -94,7 +99,8 @@ def is_supported_feature_combination(feature_combination):
@(''.join([' ' + p + ', \\\n' for p in params]))@
@[ end if]@
logger.get_name(), \
__VA_ARGS__)
rclcpp::get_c_string(RCLCPP_FIRST_ARG(__VA_ARGS__, "")) \
RCLCPP_ALL_BUT_FIRST_ARGS(__VA_ARGS__,""))

@[ end for]@
#endif
Expand Down
12 changes: 12 additions & 0 deletions rclcpp/src/rclcpp/utilities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -353,3 +353,15 @@ rclcpp::sleep_for(const std::chrono::nanoseconds & nanoseconds)
// Return true if the timeout elapsed successfully, otherwise false.
return !g_is_interrupted;
}

const char *
rclcpp::get_c_string(const char * string_in)
{
return string_in;
}

const char *
rclcpp::get_c_string(const std::string & string_in)
{
return string_in.c_str();
}
17 changes: 17 additions & 0 deletions rclcpp/test/test_logging.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,23 @@ TEST_F(TestLoggingMacros, test_logging_named) {
EXPECT_EQ("message 3", g_last_log_event.message);
}

TEST_F(TestLoggingMacros, test_logging_string) {
for (std::string i : {"one", "two", "three"}) {
RCLCPP_DEBUG(g_logger, "message " + i);
Copy link
Member

Choose a reason for hiding this comment

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

Can you add at least one test case that uses multiple arguments, so that the "all but first argument" style macros are being exercised?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have added new tests, with more than one argument, but I understand that possible uses are:

  • RCLCPP_DEBUG(g_logger, std::string("message " + i));
  • RCLCPP_DEBUG(g_logger, std::string("message " "one"));
  • RCLCPP_DEBUG(g_logger, std::string("message %d"), 1); //This works, but I am not sure if it is correct
  • RCLCPP_DEBUG(g_logger, std::string("message %d %d %d %d"), 1, 2, 3, 4)); //This works, but I am not sure if it is correct
  • RCLCPP_DEBUG(g_logger, "message %d %d %d %d", 1, 2, 3, 4)); // standard use

but never:

  • RCLCPP_DEBUG(g_logger, std::string("message "), std::string("one"));

Only first argument is possible to be a string. If I am wrong, let me know, because I am not really sure if this can happen...

Copy link
Member

Choose a reason for hiding this comment

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

That looks right to me, the documentation as it stands is that the first string is a format string (which may have no format arguments) and the rest of the arguments are input for the format string:

http://docs.ros2.org/bouncy/api/rclcpp/logging_8hpp.html#a44818c8a1fd292cd0e81759e956765d7

}
EXPECT_EQ(3u, g_log_calls);
EXPECT_EQ("message three", g_last_log_event.message);

RCLCPP_DEBUG(g_logger, "message " "four");
EXPECT_EQ("message four", g_last_log_event.message);

RCLCPP_DEBUG(g_logger, std::string("message " "five"));
EXPECT_EQ("message five", g_last_log_event.message);

RCLCPP_DEBUG(g_logger, std::string("message %s"), "six");
EXPECT_EQ("message six", g_last_log_event.message);
}

TEST_F(TestLoggingMacros, test_logging_once) {
for (int i : {1, 2, 3}) {
RCLCPP_INFO_ONCE(g_logger, "message %d", i);
Expand Down