使用boost.python从UTF-8编码的char*返回python unicode实例

5 投票
1 回答
1637 浏览
提问于 2025-04-16 12:12

我正在尝试做一件应该很简单的事情,但在现有的文档中找不到太多帮助。

在一个Python 2的项目中,我想把一个经过gettext翻译的字符串列表返回为Python中的unicode实例。gettext()的返回值是一个UTF-8编码的字符指针,这个应该很简单就能用PyUnicode_FromString转换成Python的unicode实例。我觉得这应该很简单,但我就是搞不清楚怎么做。

根据Ignacio Vazquez-Abrams和Thomas K的评论,我确实成功地为单个字符串实现了这一点;在这种情况下,你可以跳过所有的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

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

撰写回答