在很多关于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可以使用与我的类几乎完全不同的类型,除了它们存储的数据类型。因此,可能抽取的信息超出必要的范围。
所以我想这个问题归结为示例中的两个空函数。然而,当然也会接受更清洁,更短或更少的“如果”链式答案。正如标题所说,它是关于模板化的类和boost :: python,而不一定是关于boost :: variant。
答案 0 :(得分:1)
这里有几个混乱的来源。首先,在Python中,object
已基本上是一个变体 - 一切都是object
。在C ++中,类模板不是类型 - 它是创建类型的方法。因此,如果您想将MyClass<T>
从C ++公开到Python,您应该只公开所有MyClass<T>s
我会编写一个执行绑定的函数模板:
template <class T>
void bind_MyClass(const char* name) {
class_<MyClass<T>>(name, init<T const&>())
.add_property("val", &MyClass<T>::getVal, &MyClass<T>::setVal);
;
}
然后只需称呼它:
bind_MyClass<float>("MyClassFloat");
bind_MyClass<double>("MyClassDouble");