拆分pybind11模块和自动类型转换的问题

时间:2018-08-14 03:25:48

标签: python c++ pybind11

我有一组用C ++编写并使用pybind11导出到Python的模块。所有这些模块都应该能够独立使用,但是它们使用在实用程序库中定义的一组通用的自定义类型。

在每个模块中都有类似下面的代码。 Color.hpp标头定义了实用程序库中使用的类型。

#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <string>
#include "Color.hpp"

std::vector<Color> buncha_colors(int n, std::string &color) {
    std::vector<Color> out;
    for (;n-- > 0;) {
        out.push_back(Color(color));
    }
    return out;
}

PYBIND11_MODULE(pb11_example_module, m) {
    m.def("buncha_colors", &buncha_colors);
}

当然,这不起作用。 Pybind不知道如何为Color对象执行类型转换。答案是(或希望不是)答案是将Color类定义为模块的一部分。之后,pybind可以执行自动类型转换。

#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <string>
#include "Colors.hpp"

std::vector<Color> buncha_colors(int n, std::string &color) {
    std::vector<Color> out;
    for (;n-- > 0;) {
        out.push_back(Color(color));
    }
    return out;
}

PYBIND11_MODULE(pb11_example_module, m) {
    pybind11::class_<Color>(m, "Color")
        .def(pybind11::init<std::string&>())
        .def("name", &Color::name);
    m.def("buncha_colors", &buncha_colors);
}

理想情况下,我想将所有这些自定义实用程序类型和关联的功能与使用它们的所有模块放在一个单独的模块中。但是我需要在使用它的每个模块中定义类型转换,或以其他方式引用它。我该怎么办?我不要pb11_example_module.Colorutils.Color等。我不知道它们之间是否兼容,这似乎是一种错误的方式。

1 个答案:

答案 0 :(得分:1)

这最初是作为编辑,但事实证明是我的答案。

所以这很有趣。使用第一个示例,其中pybind模块中未导出Color ...

$ python
>>> import pb11_example_module
>>> pb11_example_module.buncha_colors(10, "red")[0].name()
TypeError: Unable to convert function return value to a Python type! The signature was
    (arg0: int, arg1: str) -> List[Color]
>>> import utils  # defines Color
>>> pb11_example_module.buncha_colors(10, "red")[0].name()
'red'

在导入示例模块之前导入实用程序库也可以。将类名"Color"更改为其他名称也不会破坏用法,因此它必须使用类型签名从另一个模块中进行类型转换。

只要在使用前定义了该C ++类型的类型转换,自动类型转换就可以工作。 pybind用于Python的类型转换实用程序是全局的,可以在运行时查找。您可以阅读有关here的所有信息。上述在使用前随时为自定义类型加载类型转换的解决方案是受支持的惯用解决方案。