更智能的方式调用boost :: python :: call?

时间:2013-11-18 14:51:11

标签: c++ boost boost-python

我编写了一个小类方法,通过boost::python从C ++调用python函数,我已经观察到纯python的速度提升:

namespace bp = boost::python;
double pyf::eval(double * const x) const
{
  bp::list lx;
  for (size_t i = 0; i < this->get_n(); i++)
    lx.append(x[i]);
  return bp::call<double>(pycb_, lx);
}

pycb_是我的PyObject*回调函数。

我的问题是:您是否知道从boost::python::list指针创建double *的更智能方法? 我目前的解决方案非常虚拟,但我发现boost::python文档很难理解,缺乏具体的例子,所以欢迎您的体验!

有关信息,我使用的是较旧版本的Boost(1.41)。此外,我的其余部分依赖于boost,我宁愿坚持boost::python并避免添加第三方pkgs。

1 个答案:

答案 0 :(得分:0)

据我所知,迭代是从这种类型的源填充Boost.Python list的唯一方法。替代迭代解决方案删除一些样板代码包括使用Boost.ForEachstd::for_each算法。

例如,以下两个代码段与原始代码等效:

double pyf::eval(double * const x) const
{
  bp::list lx;
  BOOST_FOREACH(double& value, boost::make_iterator_range(x, x + this->get_n()))
    lx.append(value);
  return bp::call<double>(pycb_, lx);
}

double pyf::eval(double * const x) const
{
  bp::list lx;
  std::for_each(x, x + this->get_n(), 
                boost::bind(&bp::list::append<double>, &lx, _1));
  return bp::call<double>(pycb_, lx);
}

这是一个嵌入式Python的基本示例,显示了两种方法:

#include <algorithm>
#include <iostream>
#include <boost/array.hpp>
#include <boost/bind.hpp>
#include <boost/foreach.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/python.hpp>

int main()
{
  Py_Initialize();

  namespace python = boost::python;
  try
  {
    python::object main = python::import("__main__");

    // Add the verbose_sum function to main.
    python::exec(
      "def verbose_sum(x):\n"
      "    print x\n"
      "    return sum(x)\n"
      "\n", main.attr("__dict__"));

    // Mockup data.
    PyObject* callback = python::object(main.attr("verbose_sum")).ptr();
    boost::array<double, 5> x_array = {{ 1, 2, 3, 4, 5 }};
    double* const x = &x_array[0];
    const std::size_t n = x_array.size();

    // Range iterator.
    {
      python::list x_list;
      BOOST_FOREACH(double& value, boost::make_iterator_range(x, x + n))
        x_list.append(value);
      std::cout << python::call<double>(callback, x_list) << std::endl;
    }

    // Algorithm with binding.
    {
      python::list x_list;
      std::for_each(x, x + n, 
                    boost::bind(&python::list::append<double>, &x_list, _1));
      std::cout << python::call<double>(callback, x_list) << std::endl;
    }
  }
  catch (python::error_already_set&)
  {
    PyErr_Print();
  }
}

输出:

[1.0, 2.0, 3.0, 4.0, 5.0]
15
[1.0, 2.0, 3.0, 4.0, 5.0]
15