【发布时间】:2016-09-12 14:44:41
【问题描述】:
在许多关于 boost::python 的示例中,您会看到类似以下内容:
using namespace boost::python;
typedef class_<std::vector<float>> VectorFloat;
当然,如果您需要double 向量,您将有第二个类,称为DoubleVector 左右。
在我看来,这不是很“pythonic”。如果 C++ 中的一个(模板化)类实际上是 python 中的一个类,它接受像, ..., type='float', ... , 这样的参数,那会更直观(我认为)。这样,该类在 pydocs 中也只出现一次,并且只需要添加一次到 boost::python module。
假设我们有一个用于 C++ 代码的简单模板类:
template <typename T>
MyClass
{
T val;
public:
MyClass(const T& tVal) : val(tVal) {}
T getVal() { return val; }
void setVal(const T& tVal) { val = tVal; }
};
现在我们要为 Python 编写一个接口。到目前为止我的想法:
使用 boost::variant
typedef boost::variant<MyClass<float>, MyClass<double>> VariantClass;
class MyPythonClass
{
VariantClass vClass;
public:
MyPythonClass(
const PyObject& tVal,
const boost::python::str& type)
{
using namespace boost::python;
std::string type_string = extract<std::string>(type);
if( type_string == "float" )
{
float f = extract<float>(tVal);
vClass = MyClass(f);
}
else if( type_string == "double" )
{
double d = extract<double>(tVal);
vClass = MyClass(d);
}
}
boost::python::PyObject* getVal()
{
// What to put here?
}
void setVal(const boost::python::PyObject& tVal)
{
//What to put here?
}
};
BOOST_PYTHON_MODULE(my_module)
{
class_<MyPythonClass>("MyClass", init<boost::python::PyObject, int, boost::python::str>).def("getVal", &MyClass::getVal());
}
这个解决方案的一个明显缺点是我猜 boost::variant 可以使用完全不同的类型,而我的类几乎相同,除了它们存储的数据类型。所以可能比必要的更多信息被抽象出来。
所以我猜这个问题归结为示例中的两个空函数。但是,当然也可以接受更简洁、更短或更少“if”链的答案。正如标题所说,它是关于模板类和 boost::python 而不一定是关于 boost::variant。
【问题讨论】:
-
要将 boost::variant 转换为 python 对象,请使用 static_visitor。要以另一种方式转换,您需要在运行时询问 python 对象的类型。
标签: python c++ templates boost boost-python