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

Posted

技术标签:

【中文标题】用 boost.python 暴露 std::vector<double>【英文标题】:exposing std::vector<double> with boost.python 【发布时间】:2009-12-20 21:31:21 【问题描述】:

我已经编写了一些生成 std​​::vector 的 C++ 代码。

我还有一个 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 in a python mailing list。

我也找到了this example,但发现它令人困惑。

我能想到几种方法

    boost::python::exec_file 方法传递一些东西 使用boost_indexing_suite_ext 使用boost::shared_ptr

哪种方法最容易上手?我似乎没有明确的方法。

以下是我查看的更多链接: from the boost website from the python website another mailing list thread

更新:

这适用于将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) 找到 C++ 类型的转换器: 标准::向量>

所以,显然我需要告诉 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 很常见,所以必须有一个明确的方法来做到这一点......对吧?

【问题讨论】:

【参考方案1】:

以下代码适用于我(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;

【讨论】:

有没有更面向对象的方法呢?而不是传递一个 python 字符串来执行.. 将向量转换为 sum 可以处理的类型并创建一个对象 sum = main_module("sum");... ?【参考方案2】:

我不确定我是否理解正确。在导出可以保存std::vector&lt;double&gt; 的类“PyVec”后,您可以导出任何以向量作为输入或返回类型的 c++ 函数。所以当然你可以在 c++ 中填充你的向量,并在 Python 中使用接口类型“PyVec”访问这些数据。

【讨论】:

是的,但是如何在我的 Python 脚本中填充向量? 索引套件定义了__setitem____getitem__ 等,因此在python 中您可以使用下标运算符[] 填充向量。你看到 boost::python 索引套件的向量示例了吗? boost.org/doc/libs/1_41_0/libs/python/test/… 我不太了解...我认为这将有助于我最了解一些与我想做的事情类似的来源。 他可能的意思是您还应该查看.cpp 文件(替换链接中的.py 扩展名)以获取完整示例...

以上是关于用 boost.python 暴露 std::vector<double>的主要内容,如果未能解决你的问题,请参考以下文章

Boost不将模块暴露给python

Boost.Python 列出所有暴露的类和属性

在 boost python 中暴露 C++ 接口

删除由 boost::python 暴露的 std::vector 中的一个指针

Boost Python 暴露 C++ 类,构造函数采用 std::list

使用 Boost.Python 设置包装类的元类