2

I want to call a C++ function that takes a pointer to an array on a Python list using boost::python. I have a solution like this:

//A function that takes a pointer to an array
void doSomething( int const n, double * a)
{
    for ( std::size_t i=0; i<n; ++i)
        a[i] += 1.;
}  

//My solution 
std::vector<double> add1 (std::vector<double> vec)
{
    doSomething(vec.size(),vec.data());
    return vec;
}

//boost::python registration 
#include <boost/python.hpp>
BOOST_PYTHON_MODULE(vector2)
{
    using namespace boost::python;
    def("doSomething", doSomething);
    def("add1", &add1);

    class_<std::vector<double> >("VectorOfDouble")
        .def(vector_indexing_suite<std::vector<double> >());
}

Which works in Python:

>>> import vector2
>>> lint=[1,2,3,4]
>>> old_vector = vector2.VectorOfDouble()
>>> old_vector.extend(arg for arg in lint)
>>> new_vector=vector2.add1(old_vector)
>>> print list(old_vector)
[1.0, 2.0, 3.0, 4.0]
>>> print list(new_vector)
[2.0, 3.0, 4.0, 5.0]

However, this requires copying the original list into a new list. As the arrays I am working with are very large, I'd prefer avoiding this. A modification of my solution like this doesn't return any errors, but the original object is not modified:

//My solution 
void add1 (std::vector<double> vec)
{
    doSomething(vec.size(),vec.data());
}

In python:

>>> import vector2
>>> lint=[1,2,3,4]
>>> old_vector = vector2.VectorOfDouble()
>>> old_vector.extend(arg for arg in lint)
>>> print list(old_vector)
[1.0, 2.0, 3.0, 4.0]
>>> vector2.add1(old_vector) 
>>> print list(old_vector)
[1.0, 2.0, 3.0, 4.0]

Is there a way to call doSomething and modify the original vector without creating a new one?

By the way, following a suggestion from another post, I also tried to write a simple wrapper to get a pointer to the first element of the vector:

std::string * pointer (std::string& p)
{
    return &p;
}

But it seems that the Boost registration of any function that returns a pointer produces a very lengthy error at compile time.

1 Answer 1

2

Note you are taking in std::vector as a copy.

Have you tried taking it in as a reference and seen what the result would be?

// take by reference
void add1 (std::vector<double>& vec)
{
    doSomething(vec.size(),vec.data());
}
Sign up to request clarification or add additional context in comments.

1 Comment

Yes, that's all it was! Thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.