boost::python: Python liste de std::vector

enfin je suis capable d'utiliser std::vector en python en utilisant l'opérateur []. Le truc est de fournir simplement un conteneur dans le boost C++ wrapper qui gère les trucs vectoriels internes:

#include <boost/python.hpp>
#include <vector>
class world
{
    std::vector<double> myvec;

    void add(double n)
    {
        this->myvec.push_back(n);
    }

    std::vector<double> show()
    {
     return this->myvec;
    }
};

BOOST_PYTHON_MODULE(hello)
{
    class_<std::vector<double> >("double_vector")
        .def(vector_indexing_suite<std::vector<double> >())
    ;

    class_<World>("World")
     .def("show", &World::show)
        .def("add", &World::add)
    ;
 }

L'autre défi est: comment faire traduire les listes en python std::les vecteurs? J'ai essayé d'ajouter une Classe C++ en attendant un paramètre std::vector et j'ai ajouté le code d'enrubannage correspondant:

#include <boost/python.hpp>
#include <vector>
class world
{
    std::vector<double> myvec;

    void add(double n)
    {
        this->myvec.push_back(n);
    }

    void massadd(std::vector<double> ns)
    {
        // Append ns to this->myvec
    }

    std::vector<double> show()
    {
     return this->myvec;
    }
};

BOOST_PYTHON_MODULE(hello)
{
    class_<std::vector<double> >("double_vector")
        .def(vector_indexing_suite<std::vector<double> >())
    ;

    class_<World>("World")
     .def("show", &World::show)
        .def("add", &World::add)
        .def("massadd", &World::massadd)
    ;
 }

mais si je le fais, je me retrouve avec le suivant Stimuler.Python.ArgumentError:

>>> w.massadd([2.0,3.0])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
Boost.Python.ArgumentError: Python argument types in
    World.massadd(World, list)
did not match C++ signature:
    massadd(World {lvalue}, std::vector<double, std::allocator<double> >)

quelqu'un peut-il me dire comment je peux accéder aux listes python dans ma fonction c++?

Merci, Daniel

23
demandé sur Arlaharen 2010-09-21 18:34:44

4 réponses

pour que votre méthode c++ accepte les listes Python, vous devez utiliser boost::python::list

void massadd(boost::python::list& ns)
{
    for (int i = 0; i < len(ns); ++i)
    {
        add(boost::python::extract<double>(ns[i]));
    }
}
25
répondu Arlaharen 2010-09-22 06:30:09

Voici ce que j'utilise:

#include <boost/python/stl_iterator.hpp>

namespace py = boost::python;

template< typename T >
inline
std::vector< T > to_std_vector( const py::object& iterable )
{
    return std::vector< T >( py::stl_input_iterator< T >( iterable ),
                             py::stl_input_iterator< T >( ) );
}

si vous trouvez le type d'entrée (py::object) trop libéral, n'hésitez pas à spécifier des types plus stricts (PY::list dans votre cas).

21
répondu rdesgroppes 2013-09-30 10:35:54

basé sur les réponses ci-dessus, j'ai créé un exemple d'accès aux listes python en C++ ainsi que de retour d'une liste python à partir d'une fonction C++:

#include <boost/python.hpp>
#include <string>

namespace py = boost::python;

// dummy class
class drow{
    public:
        std::string word;
        drow(py::list words);
        py::list get_chars();
};

// example of passing python list as argument (to constructor)
drow::drow(py::list l){
    std::string w;
    std::string token;
    for (int i = 0; i < len(l) ; i++){
        token = py::extract<std::string>(l[i]);
        w += token;
    }
    this -> word = w;
}

// example of returning a python list
py::list drow::get_chars(){
    py::list char_vec;
    for (auto c : word){
        char_vec.append(c);
    }
    return char_vec;
}

// binding with python
BOOST_PYTHON_MODULE(drow){
    py::class_<drow>("drow", py::init<py::list>())
        .def("get_chars", &drow::get_chars);
}

Pour construire un exemple et un test de script python prendre un coup d'oeil ici

merci à Arlaharen & rdesgroppes pour les pointeurs (jeu de mots non prévu).

3
répondu Andreas Grivas 2015-02-13 16:28:47

pour obtenir la conversion automatique des listes python, vous devez définir un convertisseur, qui

  1. vérifie si la liste est convertible à votre type (c'est-à-dire qu'il s'agit d'une séquence; en outre, vous pouvez également vérifier si tous les éléments sont du type requis, mais qui peut être manipulé dans la deuxième étape aussi bien)
  2. renvoie le nouvel objet, si la première étape a réussi; jeter l'exception si un élément de séquence n'est pas convertible à ce dont vous avez besoin.

je ne pouvez pas trouver quelque chose d'autre que mon code, vous pouvez copier-coller ce modèle (il est spécialisé à la fin de ce fichier pour divers types contenus).

1
répondu eudoxos 2011-08-10 08:16:24