Return python unicode instances from UTF-8 encoded char* using boost.python
I'm trying to do something which should be very simple, but I'm not having much luck figuring out how from the existing documentation.
For a python 2 project I am trying to return a list gettext-translated string as a unicode instances to python. Th开发者_C百科e return value for gettext() is a UTF-8 encoded char*, which should be pretty simple to convert to a python unicode instrance using PyUnicode_FromString. I have a feeling this is trivial to do, but I can't seem to figure out how.
Basd on comments from Ignacio Vazquez-Abrams and Thomas K I did get this working for a single string; for that case you can bypass all the boost.python infrastructure. Here is an example:
PyObject* PyMyFunc() {
const char* txt = BaseClass::MyFunc();
return PyUnicode_FromString(txt);
}
which is exposed with the usual def statement:
class_<MyCclass>("MyClass")
.def("MyFunc", &MyClass::PyMyFunc);
Unfortuantely this does not work when you want to return a list of unicode instances. This is my naive implementation:
boost::python::list PyMyFunc() {
std::vector<std::string> raw_strings = BaseClass::MyFunc();
std::vector<std::string>::const_iterator i;
boost::python::list result;
for (i=raw_strings.begin(); i!=raw_strings.end(); i++)
result.append(PyUnicode_FromString(i->c_str()));
return result;
}
but this does not compile: boost::python::list does seem to handle PyObject values.
With some help from the C++-SIG mailinglist I have this working now. There are two extra steps needed:
- use boost::python::handle<> to create a C++ wrapper around the PyObject* which takes care of reference handling
- use boost::python::object to create a C++ wrapper around the handle, which allows using a PyObject* instance as a (reasonably) normal C++ class instance, and thus something boost::python::list can handle.
With that knowledge the working code looks like this:
boost::python::list PyMyFunc() {
std::vector<std::string> raw_strings = BaseClass::MyFunc();
std::vector<std::string>::const_iterator i;
boost::python::list result;
for (i=raw_strings.begin(); i!=raw_strings.end(); i++)
result.append(
boost::python::object(
boost::python::handle<>(
PyUnicode_FromString(i->c_str()))));
return result;
}
精彩评论