How to satisfy argument error std::vector<double, std::allocator<double>>

1.4k views Asked by At

When calling a method an error gets thrown.

Traceback (most recent call last):
 File "./test.py", line 10, in <module>
    print prob._objfun_impl(data1)
Boost.Python.ArgumentError: Python argument types in
    _base._objfun_impl(cassini_1, tuple)
did not match C++ signature:
    _objfun_impl(pagmo::problem::python_base {lvalue}, std::vector<double, 
std::allocator<double> >)

How would I go about writing python code that would satisfy the method arguments?

This is in the PyGMO python library, its the PyGMO 1.7 version but the updated version does not contain the necessary problems in it.

Edit (added the code the causes the problem) :

from PyGMO import *
prob = problem.cassini_1()
prob._objfun_impl((1.0,1.0))

I realize the tuple wont satisfy the arguments, however I don't know what would

1

There are 1 answers

0
sehe On

Borrowing heavily from this excellent answer: Feeding a Python list into a function taking in a vector with Boost Python I created the following 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)
    ;
}

Build with:

g++ -fPIC -std=c++14 -Os -shared -o sotest.so main.cpp -lpython2.7 -lboost_python -I /usr/include/python2.7

Test with python script:

#!/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))

Prints

Values: 3
Values: 5