栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

boost :: python传递python :: list的引用

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

boost :: python传递python :: list的引用

简而言之,Boost.Python使用其TypeWrappers维护Python参数传递语义。因此,当将Python中的列表传递给公开的C
++函数时,可以通过接受Python列表作为

boost::python::list
对象来创建和维护引用。


详细的答案实际上对此有更深入的了解。在深入研究之前,让我先扩展一些语义以避免混淆。借助Python的垃圾回收和按对象传递语义,通常的经验法则是将Boost.Python
TypeWrappers视为智能指针。

  • 如果函数接受该列表作为
    boost::python::list
    对象,那么C ++现在可以引用Python对象。Python列表的生存期将延长到至少与
    booot::python::list
    对象一样长。
  • 如果将Python列表转换为其他类型,例如
    std::vector
    ,则C ++已构造一个副本到Python列表。此副本与原始列表没有关联。

这是一个C ++模块的简单示例,可以将其传递给Python列表,维护其句柄并打印其内容:

#include <iostream> // std::cout#include <utility>  // std::make_pair#include <boost/foreach.hpp>#include <boost/python.hpp>#include <boost/python/stl_iterator.hpp>boost::python::list list;/// @brief Store handle to the list.////// @param pylist Python list for which a handle will be maintained.void set(const boost::python::list& pylist){  // As the boost::python::list object is smart-pointer like, this  // creates a reference to the python list, rather than creating a   // copy of the python list.  list = pylist;}// Iterate over the current list, printing all ints.void display(){  std::cout << "in display" << std::endl;  typedef boost::python::stl_input_iterator<int> iterator_type;  BOOST_FOREACH(const iterator_type::value_type& data,      std::make_pair(iterator_type(list), // begin         iterator_type()))    // end  {    std::cout << data << std::endl;  }}BOOST_PYTHON_MODULE(example) {  namespace python = boost::python;  python::def("set",     &set);  python::def("display", &display);}

及其用法:

>>> import example>>>>>> x = range(2)>>> x[0, 1]>>> example.set(x)>>> example.display()in display01>>> x[:] = range(7, 10)>>> example.display()in display789

一个在问题带来的复杂性是阅读在C Python列表的愿望 任何时候 。在最复杂的情​​况下, 任何时间 都可以在C 线程内的 任何时间
点发生。

让我们从基础开始:Python的全局解释器锁定(GIL)。简而言之,GIL是解释器周围的互斥体。如果线程正在执行任何会影响python受管理对象的引用计数的操作,则它需要获取GIL。有时引用计数不是很透明,请考虑:

typedef boost::python::stl_input_iterator<int> iterator_type;iterator_type iterator(list);

尽管

boost::python::stl_input_iterator
接受
list
作为常量引用,但它会从构造函数中创建对Python列表的引用。

在前面的示例中,由于没有C 线程,因此所有操作都在获取GIL时发生。但是,如果

display()
可以随时从C 中调用它,则需要进行一些设置。

首先,模块需要让Python初始化GIL以进行线程化。

BOOST_PYTHON_MODULE(example) {  Pyeval_InitThreads(); // Initialize GIL to support non-python threads.  ...}

为了方便起见,让我们创建一个简单的类来帮助管理GIL:

/// @brief RAII class used to lock and unlock the GIL.class gil_lock{public:  gil_lock()  { state_ = PyGILState_Ensure(); }  ~gil_lock() { PyGILState_Release(state_);   }private:  PyGILState_STATE state_;};

为了显示与C ++线程的交互,让我们向模块添加功能,使应用程序可以安排显示列表内容的延迟时间。

/// @brief Entry point for delayed display thread.////// @param Delay in seconds.void display_in_main(unsigned int seconds){  boost::this_thread::sleep_for(boost::chrono::seconds(seconds));  gil_lock lock; // Acquire GIL.  display();     // Can safely modify python objects.  // GIL released when lock goes out of scope.}/// @brief Schedule the list to be displayed.////// @param Delay in seconds.void display_in(unsigned int seconds){  // Start detached thread.  boost::thread(&display_in_main, seconds).detach();}

这是完整的示例:

#include <iostream> // std::cout#include <utility>  // std::make_pair#include <boost/foreach.hpp>#include <boost/python.hpp>#include <boost/python/stl_iterator.hpp>#include <boost/thread.hpp>boost::python::list list;/// @brief Store handle to the list.////// @param pylist Python list for which a handle will be maintained.void set(const boost::python::list& pylist){  list = pylist;}// Iterate over the current list, printing all ints.void display(){  std::cout << "in display" << std::endl;  typedef boost::python::stl_input_iterator<int> iterator_type;  BOOST_FOREACH(const iterator_type::value_type& data,      std::make_pair(iterator_type(list), // begin         iterator_type()))    // end  {    std::cout << data << std::endl;  }}/// @brief RAII class used to lock and unlock the GIL.class gil_lock{public:  gil_lock()  { state_ = PyGILState_Ensure(); }  ~gil_lock() { PyGILState_Release(state_);   }private:  PyGILState_STATE state_;};/// @brief Entry point for delayed display thread.////// @param Delay in seconds.void display_in_main(unsigned int seconds){  boost::this_thread::sleep_for(boost::chrono::seconds(seconds));  gil_lock lock; // Acquire GIL.  display();     // Can safely modify python objects.  // GIL released when lock goes out of scope.}/// @brief Schedule the list to be displayed.////// @param Delay in seconds.void display_in(unsigned int seconds){  // Start detached thread.  boost::thread(&display_in_main, seconds).detach();}BOOST_PYTHON_MODULE(example) {  Pyeval_InitThreads(); // Initialize GIL to support non-python threads.  namespace python = boost::python;  python::def("set",        &set);  python::def("display",    &display);  python::def("display_in", &display_in);}

及其用法:

>>> import example>>> from time import sleep>>> >>> x = range(2)>>> example.set(x)>>> example.display()in display01>>> example.display_in(3)>>> x[:] = range(7, 10)>>> print "sleeping"sleeping>>> sleep(6)in display789

当Python控制台在

sleep(6)
调用中阻塞6秒钟时,C ++线程获取了GIL,显示了list的内容
x
,并释放了GIL。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/669431.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号