使用 pybind11 在 C++ 中将 Python class 表示为 std::variant 中的类型
Expressing a Python class as a type in std::variant in C++ using pybind11
下面的工作示例 returns,一个由 float 和 int64_t 组成的 variant 类型向量到 Python。目的(由注释代码行 ** 说明)是通过启用在 C++ 中构建的 Decimal (python class) 传递回 [=20= 来为此添加更多功能] 在相同的结构中。
#include <pybind11/pybind11.h>
#include <vector>
#include <variant>
#include <string>
#include <pybind11/stl.h>
#include <pybind11/complex.h>
#include <pybind11/functional.h>
#include <pybind11/chrono.h>
namespace py = pybind11;
// Importing Decimal class, as shown here
// https://pybind11.readthedocs.io/en/stable/advanced/pycpp/object.html?highlight=Decimal(#accessing-python-libraries-from-c
py::object Decimal = py::module_::import("decimal").attr("Decimal");
//typedef std::variant<float, int64_t, Decimal> Listtypes; // **
typedef std::variant<float, int64_t> Listtypes;
std::vector<ListTypes> returnList() {
std::vector<ListTypes> list(3);
int64_t integerVal = 987654321;
float floatVal = 1.01;
// Constructing python object, as shown here
//https://pybind11.readthedocs.io/en/stable/advanced/pycpp/object.html#callingpythonfunctions
py::object pi = Decimal("3.14159");
list[0] = integerVal;
list[1] = floatVal;
//list[2] = pi; // **
return list;
}
PYBIND11_MODULE(pBind, m) {
m.def("returnList", &returnList, "Function to return list of differing types");
}
所以要解决这个问题,是否可以将 Decimal 表示为 std::variant 的一部分,以便它可以与向量一起传递回 Python,或者解决方案不是那么简单吗?
您不能直接将 pi
变量添加到 std::variant
向量中,因为它的类型是 py::object
。您 可以 将其添加到您的 ListTypes
中,因此只需更改行
typedef std::variant<float, int64_t, py::object> Listtypes;
但是 Python 一侧的列表将是 [987654321, 1.0099999904632568, Decimal(3.14159)]
我认为您更愿意使用 casting offered by pybind 将 pi
变量转换为浮点型,这样您的代码就变成了
#include <pybind11/pybind11.h>
#include <vector>
#include <variant>
#include <string>
#include <pybind11/stl.h>
#include <pybind11/complex.h>
#include <pybind11/functional.h>
#include <pybind11/chrono.h>
namespace py = pybind11;
// Importing Decimal class, as shown here
// https://pybind11.readthedocs.io/en/stable/advanced/pycpp/object.html?highlight=Decimal(#accessing-python-libraries-from-c
py::object Decimal = py::module_::import("decimal").attr("Decimal");
//typedef std::variant<float, int64_t, Decimal> Listtypes; // **
typedef std::variant<float, int64_t> Listtypes;
std::vector<ListTypes> returnList() {
std::vector<ListTypes> list(3);
int64_t integerVal = 987654321;
float floatVal = 1.01;
// Constructing python object, as shown here
//https://pybind11.readthedocs.io/en/stable/advanced/pycpp/object.html#callingpythonfunctions
py::object pi = Decimal("3.14159");
list[0] = integerVal;
list[1] = floatVal;
list[2] = pi.cast<float>(); // we cast to float
return list;
}
PYBIND11_MODULE(pBind, m) {
m.def("returnList", &returnList, "Function to return list of differing types");
}
下面的工作示例 returns,一个由 float 和 int64_t 组成的 variant 类型向量到 Python。目的(由注释代码行 ** 说明)是通过启用在 C++ 中构建的 Decimal (python class) 传递回 [=20= 来为此添加更多功能] 在相同的结构中。
#include <pybind11/pybind11.h>
#include <vector>
#include <variant>
#include <string>
#include <pybind11/stl.h>
#include <pybind11/complex.h>
#include <pybind11/functional.h>
#include <pybind11/chrono.h>
namespace py = pybind11;
// Importing Decimal class, as shown here
// https://pybind11.readthedocs.io/en/stable/advanced/pycpp/object.html?highlight=Decimal(#accessing-python-libraries-from-c
py::object Decimal = py::module_::import("decimal").attr("Decimal");
//typedef std::variant<float, int64_t, Decimal> Listtypes; // **
typedef std::variant<float, int64_t> Listtypes;
std::vector<ListTypes> returnList() {
std::vector<ListTypes> list(3);
int64_t integerVal = 987654321;
float floatVal = 1.01;
// Constructing python object, as shown here
//https://pybind11.readthedocs.io/en/stable/advanced/pycpp/object.html#callingpythonfunctions
py::object pi = Decimal("3.14159");
list[0] = integerVal;
list[1] = floatVal;
//list[2] = pi; // **
return list;
}
PYBIND11_MODULE(pBind, m) {
m.def("returnList", &returnList, "Function to return list of differing types");
}
所以要解决这个问题,是否可以将 Decimal 表示为 std::variant 的一部分,以便它可以与向量一起传递回 Python,或者解决方案不是那么简单吗?
您不能直接将 pi
变量添加到 std::variant
向量中,因为它的类型是 py::object
。您 可以 将其添加到您的 ListTypes
中,因此只需更改行
typedef std::variant<float, int64_t, py::object> Listtypes;
但是 Python 一侧的列表将是 [987654321, 1.0099999904632568, Decimal(3.14159)]
我认为您更愿意使用 casting offered by pybind 将 pi
变量转换为浮点型,这样您的代码就变成了
#include <pybind11/pybind11.h>
#include <vector>
#include <variant>
#include <string>
#include <pybind11/stl.h>
#include <pybind11/complex.h>
#include <pybind11/functional.h>
#include <pybind11/chrono.h>
namespace py = pybind11;
// Importing Decimal class, as shown here
// https://pybind11.readthedocs.io/en/stable/advanced/pycpp/object.html?highlight=Decimal(#accessing-python-libraries-from-c
py::object Decimal = py::module_::import("decimal").attr("Decimal");
//typedef std::variant<float, int64_t, Decimal> Listtypes; // **
typedef std::variant<float, int64_t> Listtypes;
std::vector<ListTypes> returnList() {
std::vector<ListTypes> list(3);
int64_t integerVal = 987654321;
float floatVal = 1.01;
// Constructing python object, as shown here
//https://pybind11.readthedocs.io/en/stable/advanced/pycpp/object.html#callingpythonfunctions
py::object pi = Decimal("3.14159");
list[0] = integerVal;
list[1] = floatVal;
list[2] = pi.cast<float>(); // we cast to float
return list;
}
PYBIND11_MODULE(pBind, m) {
m.def("returnList", &returnList, "Function to return list of differing types");
}