从这个出色的答案中大量借鉴:将 Python 列表输入到使用 Boost Python 接收向量的函数中,我创建了以下MVCE:
Live On Coliru
#define BOOST_NO_AUTO_PTR
#include <boost/python/class.hpp>
#include <boost/python/def.hpp>
#include <boost/python/stl_iterator.hpp>
#include <boost/python/module.hpp>
#include <vector>
namespace pagmo { namespace problem {
struct python_base {
std::string _objfun_impl(std::vector<double> values) {
return "Values: " + std::to_string(values.size());
}
};
struct cassini_1 : python_base { };
} }
/// @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;
}
};
using namespace boost::python;
BOOST_PYTHON_MODULE(sotest) {
iterable_converter()
.from_python<std::vector<double> >()
;
class_<pagmo::problem::cassini_1>("cassini_1")
.def("_objfun_impl", &pagmo::problem::cassini_1::_objfun_impl)
;
}
构建:
g++ -fPIC -std=c++14 -Os -shared -o sotest.so main.cpp -lpython2.7 -lboost_python -I /usr/include/python2.7
用python脚本测试:
#!/usr/bin/env python
import sotest
prob = sotest.cassini_1()
print (prob._objfun_impl([1,2,3]))
values = [1,2,3];
values.extend([3.1415926, 42]);
print (prob._objfun_impl(values))
印刷
Values: 3
Values: 5