使用boost.python暴露std::vector<double>

4 投票
2 回答
8040 浏览
提问于 2025-04-15 17:13

我写了一些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> >());
}

这似乎可以工作,但据我了解,它只为我的Python脚本提供了一个名为“PyVec”的类,而不是我需要的数据。我理解错了吗?

我还看到其他人使用过boost::shared_ptr在一个Python邮件列表中。

我还找到过这个例子,但觉得有点混乱。

我能想到几种方法:

  1. 把某些东西传给boost::python::exec_file方法
  2. 使用boost_indexing_suite_ext
  3. 使用boost::shared_ptr

哪种方法最简单呢?对我来说,没有一种方法是清晰的。

这里是我看过的一些链接: 来自boost网站 来自Python网站 另一个邮件列表讨论

更新:

这段代码可以把一个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: No to_python (by-value) converter found for C++ type: 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 个回答

3

我不太确定我是否理解正确。你导出的类“PyVec”可以存放std::vector<double>,那么你就可以导出任何接受这个向量作为输入或返回类型的C++函数。当然,你可以在C++中填充这个向量,然后通过接口类型“PyVec”在Python中访问这些数据。

12

以下的代码对我来说是有效的(使用的是Python 2.6和Boost 1.39)。这段代码和你的代码几乎一样,只是没有包含BOOST_PYTHON_MODULE这一行(但有定义vector的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;
}

撰写回答