2009-12-20 6 views
4

J'ai écrit du code C++ qui génère un fichier std :: vector.exposant std :: vector <double> avec boost.python

J'ai aussi un script python qui manipule certaines données que, pour l'instant, je déclare comme ceci (ci-dessous).

import numpy 
x = numpy.random.randn(1000) 
y = numpy.random.randn(1000) 

Je peux exécuter le script correctement. De mon code C++:

using namespace boost::python; 
    try{ 
      Py_Initialize(); 
      object main = import("__main__"); 
      object global(main.attr("__dict__")); 
      object result = exec_file("scatterPlot.py", global, global); 
      Py_Finalize(); 
    } 
    catch(error_already_set){ 
      PyErr_Print(); 
    } 

    return; 

Je n'ai aucune idée de comment obtenir mes données C++ en python. J'en ai beaucoup, mais il n'y a rien de définitif.

J'ai dans mon C++

BOOST_PYTHON_MODULE(vector_indexing_suite_ext){ 
     boost::python::class_<std::vector<double> >("PyVec") 
     .def(boost::python::vector_indexing_suite<std::vector<double> >()); 
} 

Cela semble fonctionner, mais que je comprends, il ne fournit qu'une classe « PyVec » pour mon script python, mais pas les données dont j'ai besoin. Ai-je tort? J'ai également vu d'autres personnes utiliser boost::shared_ptr in a python mailing list.

J'ai également trouvé this example mais je l'ai trouvé confus.

je peux penser à quelques approches

  1. passe quelque chose à la méthode boost::python::exec_file
  2. Utilisation du boost_indexing_suite_ext
  3. Uinsg boost::shared_ptr

Quelle approche est plus facile d'y aller? Aucune approche ne me semble claire.

Voici quelques liens que j'ai regardé: from the boost website from the python website another mailing list thread

MISE À JOUR:

Cela fonctionne pour passer un int à mon code python comme ci-dessous

int main(){ 
     int five_squared=0; 
     int a =3; 
     try { 
       Py_Initialize(); 
       object main_module = import("__main__"); 
       object main_namespace = main_module.attr("__dict__"); 
       main_namespace["var"]=a; 
       object ignored = exec("result = 5 ** var", main_namespace); 
       five_squared = extract<int>(main_namespace["result"]); 
     } catch(error_already_set) { 
       PyErr_Print(); 
     } 
     std::cout << five_squared << std::endl; 
     return 0; 
} 

Mais je veux passer un vecteur, quand j'essaie de le faire de la même manière que ci-dessus, je reçois s erreur

TypeError: No to_python (by-value) converter found for C++ type: std::vector >

Donc, évidemment, j'ai besoin de dire à python comment faire face à std :: vector. Je pense que ce code pourrait aider avec ça.

BOOST_PYTHON_MODULE(vector_indexing_suite_ext){ 
     boost::python::class_<std::vector<double> >("PyVec") 
     .def(boost::python::vector_indexing_suite<std::vector<double> >()); 
} 

Mais puisque std :: vector est assez commun, il doit y avoir une manière définie de le faire ... non?

Répondre

11

Le code suivant fonctionne pour moi (Python 2.6, Boost 1.39). C'est presque le même que votre code, sauf sans la ligne BOOST_PYTHON_MODULE elle-même (mais avec la définition class_ pour le vecteur). BOOST_PYTHON_MODULE doit uniquement être utilisé lors de la création de modules d'extension.

#include <iostream> 
#include <boost/python.hpp> 
#include <boost/python/suite/indexing/vector_indexing_suite.hpp> 
using namespace boost::python; 
using namespace std; 

int main() 
{ 
    vector<double> vec; 
    vec.push_back(1.2); 
    vec.push_back(3.4); 
    try { 
      Py_Initialize(); 

      boost::python::class_<std::vector<double> >("PyVec") 
      .def(boost::python::vector_indexing_suite<std::vector<double> >()); 

      object main_module = import("__main__"); 
      object globals = main_module.attr("__dict__"); 
      globals["var"]=vec; 
      object ignored = exec("result = sum(var)", globals, globals); 
      double result = extract<double>(globals["result"]); 
      std::cout << result << std::endl; 
    } catch(error_already_set) { 
      PyErr_Print(); 
    } 
    return 0; 
} 
+0

génial, cela aide vraiment – devin

+0

Y at-il une façon plus orientée objet de le faire? Plutôt que de passer une chaîne de python pour l'exécution .. a convertir le vecteur en un type que sum pourrait gérer et créer un objet sum = main_module ("sum"); ...? – SullX

2

Je ne suis pas sûr si je comprends bien. Après avoir exporté votre classe "PyVec" qui peut contenir std::vector<double>, vous pouvez exporter n'importe quel vecteur de prise de fonction C++ en tant que type d'entrée ou de retour. Alors bien sûr vous pouvez peupler votre vecteur dans C++ et accéder à ces données en Python avec le type interfacé "PyVec".

+0

Oui mais comment faire pour remplir le vecteur dans mon script Python? – devin

+0

La suite d'indexation définit, entre autres, '__setitem__' et' __getitem__', donc à l'intérieur de python vous pouvez remplir le vecteur avec l'opérateur d'indice []. Avez-vous vu l'exemple vectoriel de la suite d'indexation boost :: python? http://www.boost.org/doc/libs/1_41_0/libs/python/test/vector_indexing_suite.py – rafak

+0

Je ne suis pas tout à fait ... Je pense que cela m'aiderait le plus voir une source qui fait quelque chose de similaire à ce que je veux faire. – devin

Questions connexes