从 std::vector<double> 到 Python 列表的转换失败(提升 python)



我想使用boost python创建从std::vector到Python列表的自定义转换。为此,我遵循to_python_converter方法。我使用了典型的转换器结构,即

template <class T, bool NoProxy = true>
struct vector_to_list {
static PyObject* convert(const std::vector<T>& vec) {
typedef typename std::vector<T>::const_iterator const_iter;
bp::list* l = new boost::python::list();
for (const_iter it = vec.begin(); it != vec.end(); ++it) {
if (NoProxy) {
l->append(boost::ref(*it));
} else {
l->append(*it);
}
}
return l->ptr();
}
static PyTypeObject const* get_pytype() { return &PyList_Type; }
};

我可以在很多情况下成功使用它,但它不适用于std::vector<double>.这是我在我的 boost python 模块中将此转换声明为的方式:

BOOST_PYTHON_MODULE(libmymodule_pywrap) {
.
.
.
bp::to_python_converter<std::vector<double, std::allocator<double> >,
vector_to_list<double, false>, true>(); // this doesn't work
bp::to_python_converter<std::vector<Eigen::VectorXd,
std::allocator<Eigen::VectorXd> >,
vector_to_list<Eigen::VectorXd, false>, true>(); // this works well
}

我收到以下编译错误:

/usr/include/boost/python/object/make_instance.hpp:27:9: error: no matching function for call to ‘assertion_failed(mpl_::failed************ boost::mpl::or_<boost::is_class<double>, boost::is_union<double>, mpl_::bool_<false>, mpl_::bool_<false>, mpl_::bool_<false> >::************)’
BOOST_MPL_ASSERT((mpl::or_<is_class<T>, is_union<T> >));
^
/usr/include/boost/mpl/assert.hpp:83:5: note: candidate: template<bool C> int mpl_::assertion_failed(typename mpl_::assert<C>::type)
int assertion_failed( typename assert<C>::type );
^
/usr/include/boost/mpl/assert.hpp:83:5: note:   template argument deduction/substitution failed:
/usr/include/boost/python/object/make_instance.hpp:27:9: note:   cannot convert ‘mpl_::assert_arg<boost::mpl::or_<boost::is_class<double>, boost::is_union<double>, mpl_::bool_<false>, mpl_::bool_<false>, mpl_::bool_<false> > >(0u, 1)’ (type ‘mpl_::failed************ boost::mpl::or_<boost::is_class<double>, boost::is_union<double>, mpl_::bool_<false>, mpl_::bool_<false>, mpl_::bool_<false> >::************’) to type ‘mpl_::assert<false>::type {aka mpl_::assert<false>}’
BOOST_MPL_ASSERT((mpl::or_<is_class<T>, is_union<T> >));

有人明白这是怎么回事吗?

我也在学习 Boost::P ython,不幸的是不明白如何解决该错误,但此示例似乎避免了错误消息,您可以根据自己的需要进行修改。

template<typename T>
struct vector_to_list
{
static PyObject* convert(const std::vector<T>& src)
{
boost::python::list result;
for (int i = 0; i < src.size(); i++)
{
result.append(src[i]);
}
return boost::python::incref(result.ptr());
}
};
...
boost::python::to_python_converter<std::vector<double>, vector_to_list<double> >();
...

但是,如果要提供以下功能:

getData()在C++中声明:

vector<double> getData() { return m_Data; }

例如,vector<double> m_Data = {1.0, 2.0, 3.0};你想要在 Python 中:

data = example.getData()
print (data)
[1.0, 2.0, 3.0]

您可以通过创建一个通用容器来实现它,并像这样注册每个容器(由此答案提供(:

/// @brief Type that allows for registration of conversions from
///        python iterable types.
struct iterable_converter
{
/// @note Registers converter from a python interable type to the
///       provided type.
template <typename Container>
iterable_converter&
from_python()
{
boost::python::converter::registry::push_back(
&iterable_converter::convertible,
&iterable_converter::construct<Container>,
boost::python::type_id<Container>());
// Support chaining.
return *this;
}
/// @brief Check if PyObject is iterable.
static void* convertible(PyObject* object)
{
return PyObject_GetIter(object) ? object : NULL;
}
/// @brief Convert iterable PyObject to C++ container type.
///
/// Container Concept requirements:
///
///   * Container::value_type is CopyConstructable.
///   * Container can be constructed and populated with two iterators.
///     I.e. Container(begin, end)
template <typename Container>
static void construct(
PyObject* object,
boost::python::converter::rvalue_from_python_stage1_data* data)
{
namespace python = boost::python;
// Object is a borrowed reference, so create a handle indicting it is
// borrowed for proper reference counting.
python::handle<> handle(python::borrowed(object));
// Obtain a handle to the memory block that the converter has allocated
// for the C++ type.
typedef python::converter::rvalue_from_python_storage<Container>
storage_type;
void* storage = reinterpret_cast<storage_type*>(data)->storage.bytes;
typedef python::stl_input_iterator<typename Container::value_type>
iterator;
// Allocate the C++ type into the converter's memory block, and assign
// its handle to the converter's convertible variable.  The C++
// container is populated by passing the begin and end iterators of
// the python object to the container's constructor.
new (storage) Container(
iterator(python::object(handle)), // begin
iterator());                      // end
data->convertible = storage;
}
};
BOOST_PYTHON_MODULE(example)
{
// Register interable conversions.
iterable_converter()
.from_python<std::vector<double> > ()
.from_python<std::vector<Eigen::VectorXd> >()    
;
}

这允许链接,嵌套vector和比indexed_vector_suite情况更Pythonic的API,例如:

data = example.doubleVector()
data[:] = example.getData()

您可以简单地使用:

data = example.getData()

相关内容

最新更新