Что не так с потоками С++ при использовании boost.python?

Обновление 2: Я не уверен, почему это все еще поддерживается (март 2014 года). Это кажется фиксированным, так как я задавал этот вопрос много лет назад. Убедитесь, что вы используете последнюю версию boost.

ОБНОВЛЕНИЕ. Возможно, для того, чтобы форматировать числа, необходимо инициализировать потоки C++, а инициализация не происходит, когда разделяемая библиотека загружается в Python?

Я звоню

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

в методе, который экспортируется в общую библиотеку через boost.python. Он ничего не печатает, но если я делаю

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

он работает.

Это важно, потому что я хочу сделать это:

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

Я обнаружил, что:

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))
    ;
}

но когда я вызываю метод str в python на объекте Bernoulli, я ничего не получаю. Я подозреваю, что более простая проблема cout связана.

Ответы

Ответ 1

Я также сталкивался с этой проблемой некоторое время назад, используя self_ns, как описано в ответах здесь Проблемы с сборкой при добавлении метода` __str__` для повышения класса Python С++

Причина использования self_ns объясняется самим Дейвом здесь http://mail.python.org/pipermail/cplusplus-sig/2004-February/006496.html


Как раз для отладки, попробуйте

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

И замените .def(self_ns::str(self)) на

class_<Bernoulli>("Bernoulli")
[...]
.def("__str__", &toString)

Ответ 2

Вы пытались использовать boost::format вместо этого? Поскольку вы уже используете boost, это не должно быть чрезмерным количеством проблем.

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

Другое дело, попробуйте передать std::endl явно на выход os.

Ответ 3

Вы пытались очистить поток до использования метода .str()?

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