python - boost python 不会自动转换 char* 数据成员

标签 python c++ boost boost-python

我试图包装一个 C++ api,但我在某些 char* 类成员上遇到了障碍。似乎 boost-python 会自动将 char const *std::string 类型转换为 python 对象(基于 this answer ),但它对 犹豫不决char* 类型。这是我得到的错误(在 python 中):

TypeError: No to_python (by-value) converter found for C++ type: char*

事实证明,这些特定的 char * 成员可能应该声明为 char const *,因为字符串永远不会改变。

我是 boost-python 的新手,所以也许有一个明显的答案,但我在谷歌上搜索这个答案时运气不佳。

有没有简单的方法告诉 boost-python 自动转换这些 char* 成员? (不幸的是,我无法将 char * 的声明更改为 char const *,因为我正在包装的 API 不受我的控制。)

更新:

好的,所以我认为我需要添加一个自定义转换器来处理 char* 成员。我开始写一个:

/** to-python convert for char* */
struct c_char_p_to_python_str
{
    static PyObject* convert(char* s) {
        return incref(object(const_cast<const char*>(s)).ptr());
    }
};

// register the QString-to-python converter
to_python_converter<char*, c_char_p_to_python_str>();

不幸的是,这不起作用。这是错误:

error: expected unqualified-id
to_python_converter<char*, c_char_p_to_python_str>();
                                                   ^

查看 docs我可以看到模板参数有这个签名:

template <class T, class Conversion, bool convertion_has_get_pytype_member=false>

因为 char* 不是一个类,所以我猜这就是它不起作用的原因。任何人都有一些见解?

更新 2:

没有。结果是 to_python_converter 需要在 BOOST_PYTHON_MODULE 调用中调用。

我得到了 to_python_converter 工作(有一些修改)。我还写了一个函数来转换 python 形式,并用 converter::registry::push_back 注册了它。我可以看到我的 to_python 代码正在运行,但 from_python 代码似乎从未运行过。

最佳答案

假设我们正在包装一些第三方 API,并抛开暴露这些指针并从外部处理它们的糟糕情况。

这是一个简短的概念证明:

#include <boost/python.hpp>
namespace bp = boost::python;

class example
{
public:
    example()
    {
        text = new char[1];
        text[0] = '\0';
    }

    ~example()
    {
        delete[] text;
    }

public:
    char* text;

};

char const* get_example_text(example* e)
{
    return e->text;
}

void set_example_text(example* e, char const* new_text)
{
    delete[] e->text;

    size_t n(strlen(new_text));
    e->text = new char[n+1];
    strncpy(e->text, new_text, n);
    e->text[n] = '\0';
}

BOOST_PYTHON_MODULE(so02)
{
    bp::class_<example>("example")
        .add_property("text", &get_example_text, &set_example_text)
        ;
}

example 类拥有text,并负责管理内存。

我们提供了一个外部的 getter 和 setter 函数。 getter 很简单,它只是提供对字符串的读取访问。 setter 释放旧字符串,分配适当大小的新内存,并复制数据。

这是在 python 解释器中的一个简单测试:

>>> import so02
>>> e = so02.example()
>>> e.text
''
>>> e.text = "foobar"
>>> e.text
'foobar'

注意事项:

  • set_example_text() 或许可以采用 std::stringbp::object 这样我们就可以轻松获得长度,并且有可能允许从不仅仅是字符串进行赋值。
  • 如果要包装的成员变量很多并且 getter/setter 模式相似,则使用模板生成代码,甚至只使用几个宏。
  • 可能有一种方法可以使用转换器来完成此操作,我明天会研究一下。但是,由于我们在这里处理内存管理,我个人更喜欢以这种方式处理它,因为它会更明显地发生什么。

关于python - boost python 不会自动转换 char* 数据成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36250943/

相关文章:

c++ - 如何在C++中扩展包含环境变量的路径

python - zmq.error.ZMQError : Address already in use, 使用 papermill 对多个笔记本运行多处理时

python - 使用Python ping 网站时必须指定IP 地址

Python内联增加多个变量

c++ - 保留不可构造对象的 vector

c++ - 虚拟继承会增加派生类的大小吗?

python - 如何使用 Ctrl+C 杀死子线程?

c++ - c++动态改变数组名

c++ - Boost代码摘录——看不懂

c++ - 将模板化类型作为字符串获取