diff --git a/cython/gtsam/tests/gtsam_test.h b/cython/gtsam/tests/gtsam_test.h index 4f161660b..659a7cd0c 100644 --- a/cython/gtsam/tests/gtsam_test.h +++ b/cython/gtsam/tests/gtsam_test.h @@ -762,4 +762,11 @@ namespace utilities { gtsam::Values localToWorld(const gtsam::Values& local, const gtsam::Pose2& base, const gtsam::KeyVector& keys); } //\namespace utilities + +#include +class RedirectCout { + RedirectCout(); + string str(); +}; + } //\namespace gtsam diff --git a/gtsam.h b/gtsam.h index cb0d4791b..98fd3e7e6 100644 --- a/gtsam.h +++ b/gtsam.h @@ -2664,4 +2664,10 @@ namespace utilities { } //\namespace utilities +#include +class RedirectCout { + RedirectCout(); + string str(); +}; + } diff --git a/gtsam/nonlinear/utilities.h b/gtsam/nonlinear/utilities.h index 07a43af53..3816f26f8 100644 --- a/gtsam/nonlinear/utilities.h +++ b/gtsam/nonlinear/utilities.h @@ -250,6 +250,32 @@ Values localToWorld(const Values& local, const Pose2& base, return world; } -} +} // namespace utilities + +/** + * For Python __str__(). + * Redirect std cout to a string stream so we can return a string representation + * of an object when it prints to cout. + * https://stackoverflow.com/questions/5419356/redirect-stdout-stderr-to-a-string + */ +struct RedirectCout { + /// constructor -- redirect stdout buffer to a stringstream buffer + RedirectCout() : ssBuffer_(), coutBuffer_(std::cout.rdbuf(ssBuffer_.rdbuf())) {} + + /// return the string + std::string str() const { + return ssBuffer_.str(); + } + + /// destructor -- redirect stdout buffer to its original buffer + ~RedirectCout() { + std::cout.rdbuf(coutBuffer_); + } + +private: + std::stringstream ssBuffer_; + std::streambuf* coutBuffer_; +}; + } diff --git a/wrap/Method.cpp b/wrap/Method.cpp index 9670fb090..a0fced078 100644 --- a/wrap/Method.cpp +++ b/wrap/Method.cpp @@ -100,9 +100,13 @@ void Method::emit_cython_pyx_no_overload(FileWriter& file, const Class& cls) const { string funcName = pyRename(name_); // leverage python's special treatment for print - if (funcName == "print_") - file.oss << " def __str__(self):\n self.print_('')\n return ''\n"; - + if (funcName == "print_") { + //file.oss << " def __str__(self):\n self.print_('')\n return ''\n"; + file.oss << " def __str__(self):\n"; + file.oss << " strBuf = RedirectCout()\n"; + file.oss << " self.print_('')\n"; + file.oss << " return strBuf.str()\n"; + } // Function definition file.oss << " def " << funcName; // modify name of function instantiation as python doesn't allow overloads