экспонирование std :: vector <double>с boost.python - PullRequest
4 голосов
/ 21 декабря 2009

Я написал некоторый код C ++, который генерирует std :: vector.

У меня также есть скрипт на python, который манипулирует некоторыми данными, которые я сейчас декларирую следующим образом (ниже).

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

Я могу запустить скрипт нормально. Из моего кода 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;

Я понятия не имею, как перенести мои данные C ++ в python. Я уже совсем немного, но, похоже, ничего определенного нет.

У меня есть в моем C ++

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

Кажется, это работает, но, как я понимаю, он предоставляет только класс "PyVec" для моего скрипта на python, но не данные, которые мне нужны. Я не прав?

Я также видел, как другие люди используют boost :: shared_ptr в списке рассылки python .

Я также нашел этот пример , но нашел его запутанным.

Я могу придумать несколько подходов

  1. Передайте что-нибудь методу boost::python::exec_file
  2. Использование boost_indexing_suite_ext
  3. Uinsg boost::shared_ptr

Какой подход легче всего начать? Ни один подход не кажется мне ясным.

Вот еще несколько ссылок, на которые я смотрел: с сайта Boost с сайта python -member-td21809375.html" rel="nofollow noreferrer"> другая ветка списка рассылки

UPDATE:

Это работает для передачи int в мой код Python, как показано ниже

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;
}

Но я хочу передать вектор, когда я пытаюсь сделать это таким же образом, как указано выше, я получаю эту ошибку

TypeError: Нет to_python (по значению) конвертер найден для типа C ++: std :: vector>

Итак, очевидно, мне нужно рассказать python, как работать с std :: vector. Я думаю, что этот код может помочь с этим.

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

Но так как std :: vector довольно распространен, должен быть определенный способ сделать это ... верно?

Ответы [ 2 ]

11 голосов
/ 11 января 2010

У меня работает следующий код (Python 2.6, Boost 1.39). Это почти то же самое, что и ваш код, за исключением самой строки BOOST_PYTHON_MODULE (но с определением class_ для вектора). BOOST_PYTHON_MODULE необходимо использовать только при создании модулей расширения.

#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;
}
2 голосов
/ 21 декабря 2009

Я не уверен, правильно ли я понимаю. После экспорта вашего класса «PyVec», который может содержать std::vector<double>, вы можете экспортировать любую функцию c ++, используя вектор в качестве входного или возвращаемого типа. Поэтому, конечно, вы можете заполнить свой вектор в c ++ и получить доступ к этим данным в Python с помощью интерфейсного типа "PyVec".

...