14

Update 2: I'm not sure why this is still being upvoted (March 2014). This appears to be fixed since I asked this question many years ago. Make sure you're using a recent version of boost.

UPDATE: Perhaps C++ streams need to be initialized in order to format numbers, and the initialization is not happening when the shared library is loaded in Python?

I am calling

cout << 1 << "!" << endl; 

in a method that is exported to a shared library via boost.python. It doesn't print anything, but if I do

cout << "%" << "!" << endl; 

it works.

This is important because I want to do this:

ostream& operator <<(ostream &os, const Bernoulli& b) {
    ostringstream oss;
    oss << b.p() * 100.0 << "%";
    return os << oss.str();
}

I exposed that by doing this:

BOOST_PYTHON_MODULE(libdistributions)
{
    class_<Bernoulli>("Bernoulli")
        .def(init<>())
        .def(init<double>())

        .def("p", &Bernoulli::p)
        .def("set_p", &Bernoulli::set_p)
        .def("not_p", &Bernoulli::not_p)

        .def("Entropy", &Bernoulli::Entropy)
        .def("KL", &Bernoulli::KL)
        .def(self_ns::str(self))
    ;
}

but when I call the str method in python on a Bernoulli object, I get nothing. I suspect the simpler cout problem is related.

7
  • I did not have problem with iostreams and boost.python... maybe the problem comes from a more subtile bug? However, the technique in the docs (1dl.us/dAD) didn't work for me, I had to write .def("__str__", &print_wrapper<Bernouilli>). What is self_ns?. Also, in your method, why not just {return os << b.p() * 100.0 << "%"; }? Commented Dec 6, 2010 at 19:59
  • @rafak the reason for doing it via ostringstream is explained in this question: stackoverflow.com/questions/2249018/… Commented Dec 6, 2010 at 20:31
  • @rafak where is print_wrapper defined? I can't find it in boost. Commented Dec 6, 2010 at 20:35
  • I should have said that it is mine: template <class C> inline std::string print_wrapper(const C& obj) { std::ostringstream os; os << obj; return os.str(); } Commented Dec 6, 2010 at 21:03
  • 1
    Possible duplicate of: stackoverflow.com/questions/2828903/… Commented Jan 25, 2011 at 4:17

3 Answers 3

3

I also run into this problem a while ago, using self_ns as outlined in the answers here Build problems when adding `__str__` method to Boost Python C++ class

The reason for using self_ns is explained by Dave himself here http://mail.python.org/pipermail/cplusplus-sig/2004-February/006496.html


Just for the sake of debugging, please try

inline std::string toString(const Bernoulli& b) 
{
   std::ostringstream s;
   s << b;
   return s.str(); 
}

And replace .def(self_ns::str(self)) with

class_<Bernoulli>("Bernoulli")
[...]
.def("__str__", &toString)
Sign up to request clarification or add additional context in comments.

6 Comments

I used self_ns as shown in the question, and it didn't fix this problem.
Can you try .def(self_ns::str(self_ns::self))?
Also you could try to add a `std::cout << "hello world << std::endl" inside your operator<< and report if your function gets called at all.
Hi, I did try that code. I'm pretty sure that Boost.Python is not properly initializing the integer-to-string code for streams. Using a printf works, but using ostream doesn't.
@Neil G: Did you try what I wrote under "Just for the sake of debugging", did that work?
|
2

Have you tried using boost::format instead? Since you are already using boost, it shouldn't be too much of a hassle.

boost::format( "%d%%" ) % ( b.p() * 100.0 )

Another thing, try passing std::endl explicitly to the output os.

6 Comments

Thanks. The number is still not being shown, but the "%" sign is there. It appears that the buffer in which the number is stringified is not being created.
Hm. I'll try to reproduce the problem then.
Thank you. Please let me know if you can't reproduce it and if you ever find a solution.
Ok, I wrote an empty Bernoulli class, with p defined as double p() {return 2.5;}; in Python, str(b) prints 250% as expected. I used boost 1.42 and Python 2.5. Which versions are you using?
I'm using boost 1.48 and Python 3.1 now.
|
0

have you tried flushing the stream prior to using the .str() method?

oss << b.p() * 100.0 << "%" << std::flush;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.