开发者

Return python unicode instances from UTF-8 encoded char* using boost.python

开发者 https://www.devze.com 2023-02-12 22:24 出处:网络
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.

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:

  1. use boost::python::handle<> to create a C++ wrapper around the PyObject* which takes care of reference handling
  2. 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;
}
0

精彩评论

暂无评论...
验证码 换一张
取 消