pybind11学习

2023-11-05

本文主要记录官方文档中 FUNCTIONS 一章的学习笔记。

对于C++ 函数的Python绑定,在前面的学习中已经有所涉及了,详见:pybind11学习 | 迈出第一步。本文主要是记录一些更加深入的知识。

1 返回值策略

Python和C++在内存管理和对象生命周期管理上存在本质的区别。为此,pybind11提供了一些返回值策略来确定由哪方管理资源。pybind11在绑定C++函数时,一个有7个返回值策略,都在py::return_value_policy(py为pybind11的别名)枚举类型中。这些策略通过model_::def()(模块函数)和class_::def()(类成员方法)来指定,默认策略为return_value_policy::automatic

返回值策略 描述
return_value_policy::take_ownership 引用现有对象(不创建一个新对象),并获取所有权。在引用计数为0时,Pyhton将调用析构函数和delete操作销毁对象。
return_value_policy::copy 拷贝返回值,这样Python将拥有拷贝的对象。该策略相对来说比较安全,因为两个实例的生命周期是分离的。
return_value_policy::move 使用std::move来移动返回值的内容到新实例,新实例的所有权在Python。该策略相对来说比较安全,因为两个实例的生命周期是分离的。
return_value_policy::reference 引用现有对象,但不拥有所有权。C++侧负责该对象的生命周期管理,并在对象不再被使用时负责析构它。注意:当Python侧还在使用引用的对象时,C++侧删除对象将导致未定义行为。
return_value_policy::reference_internal 返回值的生命周期与父对象的生命周期相绑定,即被调用函数或属性的thisself对象。这种策略与reference策略类似,但附加了keep_alive<0, 1>调用策略保证返回值还被Python引用时,其父对象就不会被垃圾回收掉。这是由def_propertydef_readwrite创建的属性getter方法的默认返回值策略。
return_value_policy::automatic 当返回值是指针时,该策略使用return_value_policy::take_ownership。反之对左值和右值引用使用return_value_policy::copy
return_value_policy::automatic_reference 和上面一样,但是当返回值是指针时,使用return_value_policy::reference策略。这是在C++代码手动调用Python函数和使用pybind11/stl.h中的casters时的默认转换策略。你可能不需要显式地使用该策略。
  • 代码使用无效的返回值策略将导致未初始化内存或多次释放数据结构,这将导致难以调试的、不确定的问题和段错误。
  • 如果函数返回值为智能指针,可以不必指定返回值策略。

2 调用策略

通过指定调用策略可以表明参数间的依赖关系,确保函数调用的稳定性

2.1 keep alive

当一个C++容器对象包含另一个C++对象时,我们需要使用该策略。keep_alive<Nurse, Patient>表明在索引Nurse被回收前,索引Patient应该被keep alive。0表示返回值,1及以上表示参数索引。1表示隐含的参数this指针,而常规参数索引从2开始。当Nurse的值在运行前被检测到为None时,调用策略将什么都不做。

通过该策略,我们可以实现将被包含对象的声明周期绑定到包含对象上,示例如下:

py::class_<List>(m, "List").def("append", &List::append, py::keep_alive<1, 2>());

py::class_<Nurse>(m, "Nurse").def(py::init<Patient &>(), py::keep_alive<1, 2>());

2.2 call guard

call_guard<T>策略允许任意T类型的scope guard应用于整个函数调用。示例如下:

m.def("foo", foo, py::call_guard<T>());

call_guard类模板源码声明如下:

/** \rst
    A call policy which places one or more guard variables (``Ts...``) around the function call. 
 \endrst */
template <typename... Ts>
struct call_guard;

template <>
struct call_guard<> {
    using type = detail::void_type;
};

template <typename T>
struct call_guard<T> {
    static_assert(std::is_default_constructible<T>::value,
                  "The guard type must be default constructible");

    using type = T;
};

template <typename T, typename... Ts>
struct call_guard<T, Ts...> {
    struct type {
        T guard{}; // Compose multiple guard types with left-to-right default-constructor order
        typename call_guard<Ts...>::type next{};
    };
};

3 默认参数

默认参数在声明时就已经被转换为Python对象了。如果默认参数为自定义类型,需要保证在class_::def中声明默认参数前,先将该自定义类型进行绑定。

py::class_<SomeType>("SomeType")
    //...

py::class_<MyClass>("MyClass").def("myFunction", py::arg("arg") = SomeType(123));

使用py::arg_v给默认参数手动添加方便阅读的注释。

py::class_<MyClass>("MyClass")
    .def("myFunction", py::arg_v("arg", SomeType(123), "SomeType(123)"));

使用空指针作为默认参数:

py::class_<MyClass>("MyClass")
    .def("myFunction", py::arg("arg") = static_cast<SomeType *>(nullptr));

4 Keyword-only参数

Python3引入Keyword-only参数语法。用法参见《Fluent Python》笔记 | 函数对象和装饰器仅限关键字参数部分。

def f(a, *, b):  # a can be positional or via keyword; b must be via keyword
    pass

f(a=1, b=2)  # good
f(b=2, a=1)  # good
f(1, b=2)  # good
f(1, 2)  # TypeError: f() takes 1 positional argument but 2 were given

pybind11提供了py::kw_only对象来实现相同的功能:

m.def("f", [](int a, int b) { /* ... */ },
      py::arg("a"), py::kw_only(), py::arg("b"));

注,该特性不能与py::args一起使用。

5 Positional-only参数

python3.8引入了Positional-only参数语法。即只能按位置赋值,不能通过关键字赋值。

pybind11通过py::pos_only()来提供相同的功能:

m.def("f", [](int a, int b) { /* ... */ },
       py::arg("a"), py::pos_only(), py::arg("b"));

6 Non-converting参数

当对Non-converting参数进行转换(包含隐式转换)时,代码会抛出错误。

Non-converting参数通过py::arg来调用.noconvert()方法指定。

m.def("floats_only", [](double f) { return 0.5 * f; }, py::arg("f").noconvert());	

7 允许/禁止None参数

使用py::arg对象的.none(bool)方法来显式地允许或禁止在Python中传入的该参数为None。在不显式指定的情况下,默认支持传递None

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

pybind11学习 的相关文章

  • Django 和 REST API 服务基于计算的请求

    我在 Django 中编写了一个机器学习应用程序 以便用户可以在表单中指定一些参数并训练模型 模型训练完成后 我想满足以下请求 curl http localhost 8000 model input XYZ 我希望 Django 返回给定
  • 编译器错误? g++ 允许可变大小的静态数组,除非函数是模板化的

    下面的代码演示了我无法解释的 gcc 4 6 2 的行为 第一个函数声明一个 vec t 类型的静态数组 其中 vec t 是 unsigned char 的 typedef 别名 第二个函数是相同的 只是 vect t 的类型是模板参数
  • C++ 中的结构填充

    如果我有一个struct在 C 中 有没有办法安全地将其读 写到跨平台 编译器兼容的文件中 因为如果我理解正确的话 每个编译器都会根据目标平台进行不同的 填充 不 那是不可能的 这是因为C 在二进制层面缺乏标准化 Don Box http
  • WCF:通用接口的序列化可能吗?

    我正在尝试实现一个服务契约 其中包含一个采用通用接口的方法 并且该通用接口本身被赋予一个接口参数 我用 ServiceKnownType 装饰了服务接口 用常规 KnownType 装饰了服务实现 并用常规 KnownType 装饰了数据契
  • 对双向链表进行排序 C++

    尝试通过遍历列表的循环来完成此操作 在循环中 我将头节点输入到我定义的排序函数中 然后使用 strcmp 来确定节点中的哪个名称是否应该排在前面 它不起作用 因为写得太早了 我通过一次沿着列表一个节点进行线性比较 而不是回去查看第一个节点是
  • 网页上的富文本编辑器

    我正在尝试在我的网页中添加一个富文本编辑器 用户可以在其中撰写评论并格式化他们所写的内容 类似于我们在此网站上撰写帖子的编辑器 谁能指出我关于此的正确方向 任何可以帮助我构建这样一个组件的教程 我还想要一个免费的产品 忘记之前提到 类似的东
  • 像 MS Excel 一样在 C++ 中舍入双精度值

    我在网上进行了搜索 但找不到解决我的问题的方法 我只是想要一个像 MS Excel 那样对双精度值进行舍入的函数 这是我的代码 include
  • MySQL:进行基本搜索

    我的数据库中有一个名称表 我希望对其进行模糊搜索 例如我的数据库包含 Name ID John Smith 1 Edward Smith 2 Gabriel Gray 3 Paul Roberts 4 目前 当我通过 python 搜索数据
  • 如何使用 SonarQube 的 C# 插件设置 FxCop 安装路径

    我正在尝试使用 SonarQube C 插件分析 NET C 项目 从C Plugin 3 0开始 即使sonar project properties中的 sonar fxcop mode skip FxCop也会自动执行 所以我将FxC
  • Doxygen 支持 C++11 模板别名(“using”语法)吗?

    我正在使用 doxygen 1 7 1 为一些 C 11 代码生成文档 它似乎忽略了我的模板别名 为了清楚起见 下面是模板别名的示例 template
  • 如何在 JSON 输出上强制采用 ISO 格式“YYYY-MM-DDThh:mm:ss.sss”?

    我有一个 ASP NET WebApi2 api 它返回一些 JSON 格式的时间戳 时间戳具有毫秒分辨率 通常我会得到这种格式的时间戳 这很好 YYYY MM DDThh mm ss sss 不幸的是 如果时间戳恰好用整秒对日期进行编码
  • 如何使用 Dictionary 属性序列化对象?

    在下面的示例代码中 我得到了这个error 元素 TestSerializeDictionary123 Customer CustomProperties 呕吐型 System Collections Generic Dictionary
  • MVC - 从视图调用控制器

    我是 MVC 新手 我正在使用 MVC 开发一个 Web 应用程序 该应用程序仅包含一个页面 所以在这个视图中我必须填充多个数据 假设应用程序是 新闻提要 应用程序 我需要填充最近的新闻 您喜欢的新闻 您朋友推荐的新闻等 那么我应该从视图到
  • 如何在C++中动态调用函数

    除了 boost Bind Function 之外 我如何在 C 中动态调用函数 PHP has obj new MyObject function doSomething obj gt function Objective C 有 MyO
  • Python:正则表达式 findall

    我使用 python 正则表达式从给定字符串中提取某些值 这是我的字符串 mystring txt sometext somemore text here some other text course course1 Id Name mar
  • python chaco轴标签时间格式

    在 Enthought 的 Chaco 中 TimeFormatter类用于格式化刻度的时间字符串 标签 有没有办法指定时间格式 类似于time strftime 源代码现在将显示月份和日期时的格式硬编码为美国风格 MMDD 我想添加一些灵
  • 我使用 difftime 的 c 函数有时会返回 65535

    我有一个函数 使用 difftime 来检测自通信心跳停止以来的时间 以秒为单位 该函数的运行速度可以达到每 50 毫秒一次 该函数似乎可以工作 除了偶尔返回 65535 之外 我可以将执行次数减少到每秒一次 因为 difftime 的返回
  • 在字典和集合上自动添加索引器是一个好的设计决策吗?

    索引器何时可以自动将项目添加到集合 字典中 这是合理的还是违反最佳实践的 public class I snip public class D Dictionary
  • Xamarin - iOS 地图上的多个多边形

    我目前正在关注this https developer xamarin com guides xamarin forms application fundamentals custom renderer map polygon map ov
  • Doctest 返回失败,但“预期”和“得到”完美匹配

    我正在尝试做列表部分的第二个练习 http www openbookproject net thinkcs python english2e ch09 html exercises 如何像计算机科学家一样思考 一书的内容 我基本上必须将给定

随机推荐

  • Jetpack-Compose 学习笔记(五)—— State 状态是个啥?又是新概念?

    系列第五篇 进入 Compose 中有关 State 状态的学习 前面几篇笔记讲了那么多内容 都是基于静态界面的展示来说的 即给我一个不变的数据 然后将它展示出来 如何在 Compose 中构建一个随数据而变化的动态界面呢 相信看完这篇就知
  • 【Vue】学习笔记-数据交互

    Vue 学习笔记 数据交互 概述 安装axios 通过axios向后台获取数据 数据交互的实现 常见错误总结 概述 基于Vue的web项目显示的所有服务端数据 都是通过Ajax获取的 官方推荐使用Axios作为Ajax库 所以本文主要讲解在
  • centos6.8升级内核

    centos6 8升级内核 1 查看内核版本命令 uname r 2 更新nss yum update nss 3 安装elrepo的yum源 升级内核需要使用elrepo的yum源 在安装yum源之前还需要我们导入elrepo的key r
  • Python使用腾讯云-短信服务发送手机短信

    目前 腾讯云短信 为客户提供 国内短信 国内语音 和 海外短信 三大服务 腾讯云短信SDK支持以下操作 国内短信 国内短信支持操作 指定模板单发短信 指定模板群发短信 拉取短信回执和短信回复状态 海外短信 海外短信支持操作 指定模板单发短信
  • 机器学习-分类模型-逻辑分类(2)

    逻辑分类简要概念 逻辑分类实际上是基于线性回归 sigmoid的一个分类器 二分类代码 import numpy as np import matplotlib pyplot as plt import sklearn linear mod
  • 一场时代的挑战与转变

    在我们的社会中 有一种现象引起了人们广泛的关注 那就是 年轻人存款 的问题 据最近的一项调查显示 大概五分之一的年轻人存款在一万元以内 10万元存款是一个 坎 存款超过10万就会超过53 7 的人 这样的数据 无疑引发了人们对于年轻人与存款
  • QT之动态库的创建、及测试代码编写

    1 新建文件和目录 在项目中选择library 右侧选择C library 如下图所示 2 按choose后 出现下面如图所示 添加库工程名字 3 选择共享库 并最好修改类名 头文件 源文件的名称 如下图所示 4 选择编译器 这里需要跟需要
  • 正则表达式之匹配字符串双引号

    字符串中可以出现转义的双引号 那么一般的正则表达式就不行了 譬如 无法正确匹配 word1 word2 word3 其结果是 word2 这里我用非获取匹配 则结果是 word2 word3 表示贪婪策略 非贪婪 pattern 非获取匹配
  • 最新Navicat Premium 16 激活中文版 适用于win和mac版

    Navicat Premium 16这是十分知名且专业的数据库开发管理工具 利用它不仅为用户提供完善的工具 可以轻松完美的帮助用户构建 管理和维护您的数据库 还与市面上主流的云数据库兼容 从而可以很好的满足不同用户们的各种使用需求 同时就算
  • element el-table 设置行高

  • Python从零开始学大概需要多久时间才能达到自主接单赚钱水平?

    我能也是学Python将近六七年的时间了 就来给大家讲讲Python吧 Python作为现在行业最受欢迎的编程语言 也是一门相对于其他的编程语言 Java C C 要更加简单 狗头保命 这是有目共睹的 那么因为Python的简单 所以现在学
  • router的使用

    路由和线路 路由router 表示当前项目全局的路由实例对象 跳转方法 push replace go back 线路route 表示当前路由页面的信息对象 获取动态路由的参数 params router跳转的两种方式 js跳转叫 编程式跳
  • 如何搭建VPN?

    搭建VPN的方法可以分为两个主要步骤 设置服务器和配置客户端 下面是一般的步骤 设置服务器 1 选择适合你需求的服务器 你可以租用云服务器 自行搭建服务器或者使用第三方VPN服务提供商 2 安装操作系统并进行基本配置 常用的操作系统有Lin
  • 如何安装黑苹果双系统

    title 黑苹果Win10双系统安装教程 小白也能秒掌握 装机装了一天 看了很多教程 踩了无数坑 终于成功了 写一篇教程防止后人踩坑吧 关于黑苹果 折腾过的人应该不陌生 自从苹果采用 Intel 的处理器 被解锁后可以安装在 Intel
  • 【前端兼容性】常见的浏览器兼容问题及解决方案

    常见浏览器兼容 前言 一 常见浏览器内核 1 Trident内核 2 Gecko内核 3 Blink内核 4 Webkit内核 5 Presto内核 已废弃 二 常见兼容性问题 1 不同浏览器的默认margin和padding不一致 2 图
  • PyQty5—第四课:GUI小程序界面设计(附完整代码)

    在第一节课中我们已经学会了PyQty5的安装 以及配置好了两个环境 如果还没有看到的小伙伴可以前去考古 点我 今天我们将会继续学习PyQty5的设计界面的认识 也会带领大家一步一步设计出一个小GUI作品 首先我们创建一个py文件 然后右击
  • OpenGL学习日记-2015.3.13——多实例渲染

    实例化 instancing 或者多实例渲染 instancd rendering 是一种连续执行多条相同渲染命令的方法 并且每个命令的所产生的渲染结果都会有轻微的差异 是一种非常有效的 实用少量api调用来渲染大量几何体的方法 OpenG
  • activiti在运行时报错:couldn‘t find a variable type that is able to serialize XXX

    activiti在启动流程实例的时候报错信息如下 Exception in thread main org activiti engine ActivitiException couldn t find a variable type th
  • 【精品源码】C#20个经典小游戏集合!

    大家好 这里是小伙整理的C 20个经典小游戏集合系列 需要的可自取下载包 C 20个经典小游戏集合项目包含内容 小游戏源码目录如下 01 21点小游戏 02 百变方块小游戏 03 打字小游戏 04 单机坦克小游戏 05 对对碰小游戏 06
  • pybind11学习

    本文主要记录官方文档中 FUNCTIONS 一章的学习笔记 对于C 函数的Python绑定 在前面的学习中已经有所涉及了 详见 pybind11学习 迈出第一步 本文主要是记录一些更加深入的知识 文章目录 1 返回值策略 2 调用策略 2