从boost :: python :: object列表中获取单个元素,以在python例程中使用

Sul*_*llX 1 c++ python boost boost-python

我有一个用于Python列表的c ++ boost python对象(PyObject上的boost包装器),

  PyObject * pyList = func(...);
  boost::python::object listObj(handle<>(boost::python::borrowed(pyList)));
Run Code Online (Sandbox Code Playgroud)

我可以通过对其执行以下操作来验证这确实是一个列表

boost::python::object np = import("numpy");
boost::python::np_difference = np.attr("diff");
np_difference(listObj);
for(int i=0; i<len(listObj); i++){                                                                                         
  double value = boost::python::extract<double>(listObj[i]);                                                                              
  cout << i << " " << value << endl;                                                                                       
} 
Run Code Online (Sandbox Code Playgroud)

它从i-1元素中减去第ith个元素并创建一个新列表,然后提取每个列表并将其打印到C ++中的stdout中。

我想做的是将此listObj与我定义为的打印功能一起使用

boost::python::object print = std.attr("print");    
Run Code Online (Sandbox Code Playgroud)

但是我只想打印我指定的元素之一。在python中,我只会写

print myList[0]
Run Code Online (Sandbox Code Playgroud)

因为它只是一个python列表。但是当我尝试

print(listObj[0]);
Run Code Online (Sandbox Code Playgroud)

在C ++中使用Boost python我得到

Error in Python: <type 'exceptions.TypeError'>: No to_python (by-value) converter found for C++ type: boost::python::api::proxy<boost::python::api::item_policies>.
Run Code Online (Sandbox Code Playgroud)

那么,如何从c ++内部访问来自python列表对象的单个元素,并在python调用中使用它,例如上述的print方法(或其他需要输入字符串的python函数)呢?

Tan*_*ury 5

boost::python::objectoperator[]回报boost::python::proxy对象。虽然proxy该类具有的隐式转换boost::python::object,但API中的许多区域都需要显式转换。

boost::python::object从显式构造A proxy应该可以解决转换异常:

print(boost::python::object(listObjString[0]));
Run Code Online (Sandbox Code Playgroud)

这是一个完整的嵌入式Python示例,演示了如何通过以下方式从列表中打印单个元素:

  • Python内置print函数
  • PyObject_Print()Python的/ C API函数
  • 通过提取对象的字符串表示形式__str__并使用进行打印std::cout
#include <boost/foreach.hpp>
#include <boost/python.hpp>
#include <boost/range/irange.hpp>

/// @brief Default flag to have PyObject_Print use the object's
///        __str__ method.  The python.h files only define the flag for
///        __repr__.
#define Py_PRINT_STR 0

int main()
{
  Py_Initialize();

  namespace python = boost::python;
  try
  {
    // Create and populate a Python list.
    // >>> list = [x for x in range(100, 103)]
    python::list list;    
    BOOST_FOREACH(int x, boost::irange(100, 103))
        list.append(x);

    // The proxy returned from a Boost.Python's operator[] provides a
    // user-defined conversion to a Boost.Python object.  In most cases,
    // explicitly invoking the conversion is required.

    // Print list[0] using the built-in function print.
    /// >>> getattr(__builtins__, 'print')(list[0])
    python::object print =
        python::import("__main__").attr("__builtins__").attr("print");
    print(python::object(list[0]));

    // Print list[1] using the Python/C API.
    // >>> import sys; sys.stdout.write(list[1].__str__())
    PyObject_Print(python::object(list[1]).ptr(), stdout, Py_PRINT_STR);
    std::cout << std::endl;

    // Print list[2] using the result of the object's __str__ method, and
    // extract a C++ string.
    std::cout << python::extract<std::string>(
                   python::object(list[2]).attr("__str__")())() << std::endl;

  }
  catch (python::error_already_set&)
  {
    PyErr_Print();
  }
}
Run Code Online (Sandbox Code Playgroud)

输出:

100
101
102
Run Code Online (Sandbox Code Playgroud)