Возвращать экземпляры Python Unicode из кодированного в UTF-8 символа char *, используя boost.python - PullRequest
5 голосов
/ 21 февраля 2011

Я пытаюсь сделать что-то, что должно быть очень простым, но мне не очень повезло, выясняя, как из существующей документации.

Для проекта Python 2 я пытаюсь вернуть строку, переведенную gettext-списком, в виде экземпляров Unicode для Python. Возвращаемое значение для gettext () - это кодированный в UTF-8 символ char *, который довольно просто преобразовать в экземпляр юникода python с использованием PyUnicode_FromString. У меня такое чувство, что это тривиально, но я не могу понять, как это сделать.

Основываясь на комментариях Игнасио Васкеса-Абрамса и Томаса К. Я получил эту работу для одной строки; в этом случае вы можете обойти всю инфраструктуру boost.python. Вот пример:

        PyObject* PyMyFunc() {
            const char* txt =  BaseClass::MyFunc();
            return PyUnicode_FromString(txt); 
    }       

, который выставляется с помощью обычного оператора def:

class_<MyCclass>("MyClass")
    .def("MyFunc", &MyClass::PyMyFunc);

К сожалению, это не работает, когда вы хотите вернуть список экземпляров Unicode. Это моя наивная реализация:

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

но это не компилируется: boost :: python :: list действительно обрабатывает значения PyObject.

1 Ответ

2 голосов
/ 22 февраля 2011

С некоторой помощью из списка рассылки C ++ - SIG у меня это работает сейчас.Требуются два дополнительных шага:

  1. используйте boost :: python :: handle <> для создания оболочки C ++ вокруг PyObject *, которая заботится об обработке ссылок
  2. , используйте boost:: python :: object для создания оболочки C ++ вокруг дескриптора, которая позволяет использовать экземпляр PyObject * в качестве (разумно) нормального экземпляра класса C ++ и, следовательно, что-то, что boost :: python :: list может обработать.

С этим знанием рабочий код выглядит так:

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