【问题标题】:Return python unicode instances from UTF-8 encoded char* using boost.python使用 boost.python 从 UTF-8 编码的 char* 返回 python unicode 实例
【发布时间】:2011-02-21 10:37:36
【问题描述】:

我正在尝试做一些应该非常简单的事情,但我没有太多运气从现有文档中弄清楚如何做。

对于一个 python 2 项目,我试图将一个列表 gettext-translated 字符串作为一个 unicode 实例返回给 python。 gettext() 的返回值是一个 UTF-8 编码的 char*,使用 PyUnicode_FromString 将其转换为 python unicode 实例应该非常简单。我觉得这很简单,但我似乎无法弄清楚如何做。

基于 Ignacio Vazquez-Abrams 和 Thomas K 的 cmets对于这种情况,您可以绕过所有 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 值。

【问题讨论】:

  • 我不明白。只打电话PyUnicode_FromString()有什么问题?
  • 大部分情况下它确实有效。例如,使用返回 PyUnicodeFromString(BaseClass::method()) 的简单包装方法,或者从 python 调用时会导致 None 或错误。
  • 您是否尝试过找出问题所在?错误可能在其他地方吗?字符串是否有可能不是有效的 UTF-8?
  • 编码确实是这里的一个重要因素:我没想到 gettext 会根据当前语言环境切换编码。添加对 bind_textdomain_codeset() 的调用以强制执行 UTF-8 输出可以正常工作。
  • 简单的 PyUnicode_FromString 现在确实适用于单个字符串。不过,当我不得不返回一个 unicode 实例列表时,我仍然在苦苦挣扎;我已经更新了问题以更好地反映我的用例,并根据您的 cmets 添加了一个用于单 unicode-return-value 的工作示例。

标签: c++ python boost boost-python


【解决方案1】:

在 C++-SIG 邮件列表的帮助下,我现在可以正常工作了。需要两个额外的步骤:

  1. 使用 boost::python::handle 围绕 PyObject* 创建一个 C++ 包装器,该包装器负责引用处理
  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;
}

【讨论】:

    猜你喜欢
    • 2018-01-14
    • 1970-01-01
    • 1970-01-01
    • 2013-05-11
    • 2013-03-22
    • 2021-08-08
    • 2019-10-30
    • 2013-09-11
    • 1970-01-01
    相关资源
    最近更新 更多