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

2023-11-29

我真的很想知道是否有可能将 python 列表的引用传递给 boost::python c++ dll。我想要实现的是我有一个Python列表,可以随时在C++中读取。 假设您在 C++ 中有一个变量来保存对列表的引用。

有什么办法可以做到这一点吗?到目前为止,我只在 python 中找到了 ctypes,我可以在其中引用原始 c 类型,在这种情况下,这没有帮助。

我很高兴收到任何建议或解决方法(一个简单的例子就很好)

问候 克里斯


简而言之,Boost.Python 通过其 TypeWrappers 维护了 Python 参数传递语义。因此,当将 Python 中的列表传递给公开的 C++ 函数时,可以通过接受 Python 列表作为引用来创建和维护引用。boost::python::list object.


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

  • 如果该函数接受列表作为boost::python::list对象,那么 C++ 现在就拥有了对 Python 对象的引用。 Python 列表的生命周期将延长至至少与booot::python::list object.
  • 如果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 display
0
1
>>> x[:] = range(7, 10)
>>> example.display()
in display
7
8
9

问题中引入的一个复杂性是希望随时读取 C++ 中的 Python 列表。在最复杂的情​​况下,任何时间可以在 C++ 线程内的任何时间点发生。

让我们从基础开始:Python全局解释器锁(吉尔)。简而言之,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 display
0
1
>>> example.display_in(3)
>>> x[:] = range(7, 10)
>>> print "sleeping"
sleeping
>>> sleep(6)
in display
7
8
9

虽然 Python 控制台阻塞了 6 秒sleep(6)调用时,C++线程获取了GIL,显示了list的内容x,并发布了GIL。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

boost::python 传递 python::list 的引用 的相关文章

  • pandas to_sql sqlalchemy 与 secure_transport 的连接

    我正在尝试将数据发送到具有 require secure transport ON 的服务器上的 mysql 数据库 当我尝试使用以下代码连接到它时 import pandas as pd import pymysql from sqlal
  • ASP.NET:获取自 1970 年 1 月 1 日以来的毫秒数

    我有一个 ASP NET VB NET 日期 我试图获取自 1970 年 1 月 1 日以来的毫秒数 我尝试在 MSDN 中寻找方法 但找不到任何东西 有谁知道如何做到这一点 从 NET 4 6 开始 该方法ToUnixTimeMillis
  • 关于在 Windows 上使用 WiFi Direct Api?

    我目前正在开发一个应用程序 我需要在其中创建链接 阅读 无线网络连接 在桌面应用程序 在 Windows 10 上 和平板电脑 Android 但无关紧要 之间 工作流程 按钮 gt 如果需要提升权限 gt 创建类似托管网络的 WiFi 网
  • 单击 form2 上的按钮触发 form 1 中的方法

    我对 Windows 窗体很陌生 我想知道是否可以通过单击表单 2 中的按钮来触发表单 1 中的方法 我的表格 1 有一个组合框 我的 Form 2 有一个 保存 按钮 我想要实现的是 当用户单击表单 2 中的 保存 时 我需要检查表单 1
  • 使用 JNI 从 Java 代码中检索 String 值的内存泄漏

    我使用 GetStringUTFChars 从使用 JNI 的 java 代码中检索字符串的值 并使用 ReleaseStringUTFChars 释放该字符串 当代码在 JRE 1 4 上运行时 不会出现内存泄漏 但如果相同的代码在 JR
  • 如何绘制多类分类器的精度和召回率?

    我正在使用 scikit learn 我想绘制精度和召回曲线 我正在使用的分类器是RandomForestClassifier scikit learn 文档中的所有资源都使用二元分类 另外 我可以绘制多类的 ROC 曲线吗 另外 我只找到
  • 使用 Python 脚本打开特定文件类型?

    如何使 Python 脚本成为特定文件类型 例如 foo 的默认应用程序 例如 当我双击 Finder Explorer 中的文件时 我希望该文件在 Python 脚本中打开 这可以在 Win 和 或 OS X 中实现吗 如果重要的话 该应
  • 如何将整数转换为 void 指针?

    在 C 中使用线程时 我面临警告 警告 从不同大小的整数转换为指针 代码如下 include
  • C++:.bmp 到文件中的字节数组

    是的 我已经解决了与此相关的其他问题 但我发现它们没有太大帮助 他们提供了一些帮助 但我仍然有点困惑 所以这是我需要做的 我们有一个 132x65 的屏幕 我有一个 132x65 的 bmp 我想遍历 bmp 并将其分成小的 1x8 列以获
  • Celery:每个工作人员的 task_acks_late 的不同设置/向 celery 添加自定义选项

    这个问题是后续问题django celery 禁用一个工作者的预取 有错误吗 https stackoverflow com questions 58290045 django celery disable prefetch for one
  • 在python中安装scipy模块时出错

    我正在尝试使用 pip 在 python 中安装 scipy 模块 它显示以下错误 Command c users sony appdata local programs python python35 32 python exe u c
  • Python 队列 get()/task_done() 问题

    我的消费者端队列 m queue get queue task done
  • 如何使用 pygame.mixer 重复音乐?

    我创建了以下使用 pygame mixer 播放 mp3 音乐的代码 然而 音乐不会重复 有什么想法可以让音乐重复播放吗 这是代码 playlist list playlist append put music here mp3 playl
  • 如何限制scrapy请求对象?

    所以我有一个蜘蛛 我认为它正在泄漏内存 结果当我检查 telnet 控制台 gt gt gt prefs 时 它只是从链接丰富的页面中抓取了太多链接 有时它会超过 100 000 个 现在我已经一遍又一遍地浏览文档和谷歌 但我找不到一种方法
  • Scrapy 抓取并跟踪 href 中的链接

    我对 scrapy 很陌生 我需要从 url 的主页跟踪 href 到多个深度 再次在 href 链接内我有多个 href 我需要遵循这些href 直到到达我想要抓取的页面 我的页面的示例 html 是 初始页 div class page
  • 有人可以提供一个使用 Amazon Web Services 的 itemsearch 的 C# 示例吗

    我正在尝试使用 Amazon Web Services 查询艺术家和标题信息并接收回专辑封面 使用 C 我找不到任何与此接近的示例 所有在线示例都已过时 并且不适用于 AWS 的较新版本 有一个开源项目CodePlex http www c
  • (de)从 CSV 序列化为对象(或者最好是类型对象的列表)

    我是一名 C 程序员 试图学习 C 似乎有一些内置的对象序列化 但我在这里有点不知所措 我被要求将测试数据从 CSV 文件加载到对象集合中 CSV 比 xml 更受青睐 因为它更简单且更易于人类阅读 我们正在创建测试数据来运行单元测试 该集
  • Server.MapPath - 给定的物理路径,预期的虚拟路径

    我正在使用这行代码 var files Directory GetFiles Server MapPath E ftproot sales 在文件夹中查找文件 但是我收到错误消息说 给定物理路径但虚拟路径 预期的 我对在 C 中使用 Sys
  • 英特尔 Pin 与 C++14

    问题 我有一些关于在 C 14 或其他 C 版本中使用英特尔 Pin 的问题 使用较新版本从较旧的 C 编译代码很少会出现任何问题 但由于 Intel Pin 是操作指令级别的 如果我使用 C 11 或 C 14 编译它 是否会出现任何不良
  • memset 未填充数组

    u32 iterations 5 u32 ecx u32 malloc sizeof u32 iterations memset ecx 0xBAADF00D sizeof u32 iterations printf 8X n ecx 0

随机推荐

  • 在 R 中结合 grid_arrange_shared_legend() 和facet_wrap_labeller()

    我正在尝试结合grid arrange shared legend and facet wrap labeller 更具体地说 我想绘制一个包含两个 ggplot 图形的图形 每个图形都有多个面板 并且有一个共同的图例 我还想将部分刻面条标
  • 使用批处理文件并排合并 csv 文件[重复]

    这个问题在这里已经有答案了 我有一个非常基本的批处理命令来将 csv 文件合并在一起 但是我需要将它们合并 以便各列并排而不是继续 每个文件上的记录数量始终相同 这是我到目前为止的基本代码 COPY File1 csv File2 csv
  • 尝试使用 XML 配置关闭一个 URL 的安全性

    我检查了几个博客 doc stackoverflow 论坛条目 但我仍然不知道我做错了什么 我想向任何人授予对 URL 的访问权限 这permitAll不起作用 因为我有自定义过滤器 所以我想创建一个单独的http元素并使用security
  • 基于 boost::asio 的慢速 http 客户端 - (分块传输)

    我正在使用以下代码 取自 boost 教程 从服务器获取 json 字符串 问题是它需要一些时间来执行 即超过 2 秒才能完成 并且客户端和服务器都在本地主机上 如果我删除程序的最后两行 即此时 while boost asio read
  • 有没有办法让 GCC/Clang 知道 C 中的继承?

    我正在编写一个 C 库 它使用一些简单的面向对象继承 如下所示 struct Base int x struct Derived struct Base base int y 现在我想将 Derived 传递给一个采用 Base 的函数 如
  • 有没有像这个网站一样进行 AES 加密的示例 Java 代码?

    http www hanewin net encrypt aes aes test htm 如果您访问该网站并输入以下内容 Key In Hex 00000000000000000000000000123456 Plain Text in
  • 具有列重新排序功能的 JQGrid

    我有一个 jqgrid 我可以使用 JQGrid 中的此选项重新排序我的列 jQuery list jqGrid sortable true 此功能让我可以重新排序所有列 但我希望某些列必须位于固定位置 有办法解决这个问题吗 提前致谢 Br
  • Laravel Eloquent 在当前月份和前 3 个月之间进行选择

    我正在尝试构建一个查询 该查询将选择数据库中现在 当月 和前 3 个月之间的所有记录 我的查询有些有效 但我想忽略该月的某一天 目前 它也选择当前日期的最后几个月 但我想忽略当前日期并使用月份的开始和结束 这是我的查询 dateS Carb
  • 通过命令行传递 karate.env 无法按预期工作[重复]

    这个问题在这里已经有答案了 我下载了空手道演示项目并做了一些小更改 在空手道配置 js 函数的第一行 karate log Environment from command line karate env 然后我从终端执行 mvn test
  • 将自定义数据从购物车项目传递到 Woocommerce 3 中的订单元

    我已经实现了一个自定义 HTML 表单 并要求提供一些数据 我的客户将传递这些数据以成功下订单 如果没有这些细节 我的订单就没有任何意义 对于 HTML 表单 我引用了下面的一些自定义 PHP 脚本 该脚本处理来自表单的 POST 数据并以
  • 在 wsimport 中使用 JAXB 绑定扩展

    我知道如何在普通 JAXB 绑定文件中启用扩展 将它们列在根元素中extensionBindingPrefixes
  • 在 PostgreSQL 中设置时间戳列的时区

    我在 PostgreSQL 表上有一个更新时间戳字段的触发器 但我想将其置于正确的时区 如何将我的列默认设置为始终处于 PST 这是我的触发器 ALTER TABLE coastal ADD latest report TIMESTAMP
  • Rails + Hotwire:为什么我的链接在单击时消失了?

    我正在尝试将 Hotwire Turbo 合并到现有的 Rails 应用程序中 我已将涡轮框架添加到简单的编辑页面 但现在当我单击后退按钮时 它会消失而不是带我到目标页面 链接很简单link to Back my model show pa
  • 获取 SciPy 的 gaussian_kde 函数使用的带宽

    我正在使用 SciPy统计数据 gaussian kde函数从数据集生成核密度估计 kde 函数x y points 这是我的代码的简单 MWE import numpy as np from scipy import stats def
  • 为什么我会收到一个编译错误,显示 error: ‘else’ without previous ‘if’?

    当我尝试编译代码时 出现错误 else 没有前面的 if Fibonacci series using recursion include
  • 如何找到两个矩形之间距离最近的两点?

    我正在尝试找到能够找到代表两个矩形之间最近距离的两个点的算法 点赞积分C and J形成下图中的最小距离 我试图不在这里重新发明轮子并使用已经经过战斗测试的东西 例如增强 几何 距离 但它只返回距离 而不返回点数 不要让事情变得过于通用 通
  • 使用 out 参数的优点和缺点是什么

    任何人都可以指出 out 参数的优缺点 当首选使用 out 参数而不仅仅是返回值时 输出参数有效地允许您从方法返回多个值 这通常比返回包含多个值的任意结构或元组更可取 有人可能会说 使用 out 参数的函数更容易忽视可能的副作用 因为它偏离
  • S3 签名 URL 在参数通过之前就过期了

    我正在尝试为 S3 存储桶对象生成签名 URL 最大过期时间为 604800 秒或 7 天 然而 经过测试 我发现链接在 24 小时内就会过期 经过一番挖掘 我发现这篇文章声称只有当 aws sdk 获得 IAM 用户授权并且 s3 库使用
  • Python正则表达式找不到子字符串,但它应该找到

    我正在尝试使用 BeautifulSoup 解析 html 来尝试提取网页标题 有时这不起作用 因为网站写得不好 例如Bad End标签 当这不起作用时 我会转到手动正则表达式 我有文字 n n n
  • boost::python 传递 python::list 的引用

    我真的很想知道是否有可能将 python 列表的引用传递给 boost python c dll 我想要实现的是我有一个Python列表 可以随时在C 中读取 假设您在 C 中有一个变量来保存对列表的引用 有什么办法可以做到这一点吗 到目前