我需要为C ++代码库构建python绑定。我使用boost :: python并且在尝试使用和返回模板公开包含函数的类时遇到了问题。这是一个典型的例子
class Foo
{
public:
Foo();
template<typename T> Foo& setValue(
const string& propertyName, const T& value);
template<typename T> const T& getValue(
const string& propertyName);
};
典型的T是字符串,双精度,矢量。
在阅读documentation之后,我尝试对所使用的每种类型使用薄包装。这是string和double的包装以及相应的类声明。
Foo & (Foo::*setValueDouble)(const std::string&,const double &) =
&Foo::setValue;
const double & (Foo::*getValueDouble)(const std::string&) =
&Foo::getValue;
Foo & (Foo::*setValueString)(const std::string&,const std::string &) =
&Foo::setValue;
const std::string & (Foo::*getValueString)(const std::string&) =
&Foo::getValue;
class_<Foo>("Foo")
.def("setValue",setValueDouble,
return_value_policy<reference_existing_object>())
.def("getValue",getValueDouble,
return_value_policy<copy_const_reference>())
.def("getValue",getValueString,
return_value_policy<copy_const_reference>())
.def("setValue",setValueString,
return_value_policy<reference_existing_object>());
它编译好,但是当我尝试使用python绑定时,我得到了一个C ++异常。
>>> f = Foo()
>>> f.setValue("key",1.0)
>>> f.getValue("key")
Traceback (most recent call last):
File "<stdin>", line 1, in ?
RuntimeError: unidentifiable C++ exception
有趣的是,当我只将Foo暴露给双重或字符串值时,即
class_<Foo>("Foo")
.def("getValue",getValueString,
return_value_policy<copy_const_reference>())
.def("setValue",setValueString,
return_value_policy<reference_existing_object>());
工作正常。 我错过了什么吗?
答案 0 :(得分:3)
这可能与您的问题没有直接关系,但我不相信使用这样的模板进行功能签名转换。我会像这样包裹它:
class_<Foo>("Foo")
.def("setValue", &Foo::setValue<double>,
return_value_policy<reference_existing_object>())
.def("getValue", &Foo::getValue<double>,
return_value_policy<copy_const_reference>())
.def("getValue", &Foo::getValue<std::string>,
return_value_policy<copy_const_reference>())
.def("setValue", &Foo::setValue<std::string>,
return_value_policy<reference_existing_object>());
如果这不起作用,您可能需要创建一些填充函数:
Foo& setValueDouble(foo& self, const string& propertyName, const double value)
{
return self.setValue(propertyName, value)
}
...
并将它们视为成员函数。
在Boost :: Python中导出多个函数重载到同一个名称是一个非常有效的事情,所以我认为这不是问题所在。
答案 1 :(得分:0)
我怀疑问题是boost :: python不知道调用“getValue”的重载 - 应该调用getValueDouble还是getValueString?如果你明确地将它们绑定为getValueString和getValueDouble(作为方法名称),我敢打赌它会起作用。
答案 2 :(得分:0)
如何为返回/获取boost :: python :: object的getter / setter创建C ++包装器?然后,您可以简单地确定您在C ++包装器中获得的类型,并将其打包/解压缩到boost :: python :: object中。
struct FooWrap : public Foo
{
using boost::python;
Foo& setValueO(const string& propertyName, const object& obj)
{
object value;
if(PyInt_Check(obj.ptr())) {
return setValue<int>(propertyName, extract<int>(obj);
} else if(PyFloat_Check(obj.ptr())) {
return setValue<double>(propertyName, extract<double>(obj);
} else if(PyString_Check(obj.ptr())) {
return setValue<std::string>(propertyName, extract<std::string>(obj);
}
// etc...
}
object getValueO(const std::string& propertyName)
{
if(determineType() == TYPE_INT) { // however you determine the type
return object(getValue<int>(propertyName));
} else if(determineType() == TYPE_DOUBLE) {
return object(getValue<double>(propertyName));
} else if(determineType() == TYPE_STRING) {
return object(getValue<std::string>(propertyName));
}
// etc...
}
};
class_<Foo>("Foo")
.def("setValue", &FooWrap::setValueO,
return_value_policy<reference_existing_object>())
.def("getValue", &FooWrap::getValueO,
return_value_policy<copy_const_reference>())