Boost.python自动转换参数

2023-12-12

我正在使用 boost.python 来包装 C++ 类“A”,该类采用字符串作为构造函数。然后我有一个函数“fun(A&arg)”,它将引用“A”作为参数。我想要一个“fun”的Python包装器,如果我传递一个对Python字符串的引用的变量,这个引用首先会自动转换为对“A”的引用。

一个例子可能会有所帮助。在 python 方面,我希望能够做到这一点:

a = 'some string'
fun(a)

然后让 'a' 实际上是(对)'A'(的引用),而不是(对原始字符串的引用)。我想这样做是因为我希望能够避免将其写为

a = A('some string')
fun(a)

(您可能有充分的理由怀疑这是一个相关的保护程序,但我们假设它对我很重要)。

这样的事情可能吗?如果不使用boost.python,也许直接使用Python-C API?

Note:我知道如果我写的话

fun('some string')

无法将对字符串的引用转换为对其他类型的引用。


这是可能的,但解决方案可能取决于 Python 实现。

例如,在 Python 2.7 中,inspect模块和sys.settrace()可以用来修改locals()在特定的框架上。这也可以在 Python/C API 中完成,但在 Python 中操作 Python 框架通常更容易管理。

在下面example.py, the update_locals()函数将更新locals()在给定的框架中:

import inspect
import sys


def _force_locals(old_frame, new_locals):
    ''' Force a new set of locals on a given frame. 

    :param old_frame: The frame to which locals will be applied.
    :type old_frame: frame.
    :param new_locals: What locals() should return for old_frame.
    :type new_locals: dict.

    .. note:: This function will force a custom trace function onto
              the old_frame.  Within the context of a trace function
              (often used for debugging), a frame's f_locals is
              modifiable.  In most execution paths, f_locals is 
              writable but not modifiable.

    '''
    # Force tracing by setting the global tracing function to
    # any non-None function.  
    if not sys.gettrace():
        sys.settrace(lambda *args, **keys: None)

    # Custom trace function that will force locals.
    def trace(frame, event, arg):
        # Update the frame's locals.
        frame.f_locals.update(new_locals)
        # Set frame to use default trace, preventing this trace
        # function from resetting the locals on each trace call.
        del frame.f_trace

    # Set the old frame's trace function to the custom trace.
    old_frame.f_trace = trace


def update_locals(frame, *refs):
    ''' Modifies a frame's locals based on the provided references.

    :param frame: The frame from which a locals will be updated.
    :type frame: frame.
    :param refs: Iterable pair of (old_ref, new_ref) tuples.
    :type refs: Iterable type of pairs.

    '''
    new_locals = frame.f_locals.copy()
    has_changes = False

    # If a frame's local has an identity patch with a provided
    # reference, then update new_locals with the new reference.
    for key, ref in new_locals.iteritems():
        for old_ref, new_ref in refs:
            if ref is old_ref:
                new_locals[key] = new_ref
                has_changes = True

    # If new_locals has changes, then force them onto the frame.
    if has_changes:
        _force_locals(frame, new_locals)

互动使用:

>>> import example
>>> import inspect
>>> x = 42
>>> x
42
>>> example.update_locals(inspect.currentframe(), (x, '3.14'))
>>> x
'3.14'

The x变量引用了int(42)对象,但是example.update_locals()功能改变x参考str('3.14') object.


能够修改调用者的框架后,下一步就是对 C++ 进行猴子修补fun()在Python中构造一个实例A如果参数是一个实例str,然后委托给 C++fun(A&)函数并更新调用者的框架。

在下面的示例中,C++Spam类型和fun(Spam&)函数暴露于_examplePython 模块。

#include <iostream>
#include <string>
#include <boost/python.hpp>

/// @brief Mockup type.
class Spam
{
public:
  explicit Spam(std::string str)
    : str_(str)
  {}

  void action()
  {
    std::cout << "Spam::action(): " << str_ << std::endl;
  }

private:
  std::string str_;
};

/// @brief Mockup function.
void fun(Spam& spam)
{
  std::cout << "fun() -> ";
  spam.action();
}

BOOST_PYTHON_MODULE(_example)
{
  namespace python = boost::python;

  python::class_<Spam>("Spam", python::init<std::string>());
  python::def("fun", &fun);
}

更高层次example模块将猴子补丁_example.fun()构建一个Spam对象如果参数提供给fun()是一个实例str并以与上面演示类似的方式操纵调用者的框架:

from _example import *

import inspect
import sys


def _force_locals(old_frame, new_locals):
    ''' Force a new set of locals on a given frame. 

    :param old_frame: The frame to which locals will be applied.
    :type old_frame: frame.
    :param new_locals: What locals() should return for old_frame.
    :type new_locals: dict.

    .. note:: This function will force a custom trace function onto
              the old_frame.  Within the context of a trace function
              (often used for debugging), a frame's f_locals is
              modifiable.  In most execution paths, f_locals is 
              writable but not modifiable.

    '''
    # Force tracing by setting the global tracing function to
    # any non-None function.  
    if not sys.gettrace():
        sys.settrace(lambda *args, **keys: None)

    # Custom trace function that will force locals.
    def trace(frame, event, arg):
        # Update the frame's locals.
        frame.f_locals.update(new_locals)
        # Set frame to use default trace, preventing this trace
        # function from resetting the locals on each trace call.
        del frame.f_trace

    # Set the old frame's trace function to the custom trace.
    old_frame.f_trace = trace


def _update_locals(frame, *refs):
    ''' Modifies a frame's locals based on the provided references.

    :param frame: The frame from which a locals will be updated.
    :type frame: frame.
    :param refs: Iterable pair of (old_ref, new_ref) tuples.
    :type refs: Iterable type of pairs.

    '''
    new_locals = frame.f_locals.copy()
    has_changes = False

    # If a frame's local has an identity patch with a provided
    # reference, then update new_locals with the new reference.
    for key, ref in new_locals.iteritems():
        for old_ref, new_ref in refs:
            if ref is old_ref:
                new_locals[key] = new_ref
                has_changes = True

    # If new_locals has changes, then force them onto the frame.
    if has_changes:
        _force_locals(frame, new_locals)


def _patch_fun():
    old_fun = fun
    # Create a function that will perform custom operations then
    # delegate to the original function.
    def patch(spam, *args, **kwargs):
        if isinstance(spam, str):
            old_spam, spam = spam, Spam(spam)

            # In the caller's frame, force the variables that reference
            # old_spam to now reference spam.
            _update_locals(
                inspect.currentframe(1), # Caller's frame.
                (old_spam, spam))

        return old_fun(spam, *args, **kwargs)
    return patch

fun = _patch_fun()

互动使用:

>>> import example
>>> s1 = example.Spam('abc')
>>> type(s1)
<class '_example.Spam'>
>>> example.fun(s1)
fun() -> Spam::action(): abc
>>> type(s1) # s1's type has not changed.
<class '_example.Spam'>
>>> s2 = 'def'
>>> type(s2)
<type 'str'>
>>> example.fun(s2)
fun() -> Spam::action(): def
>>> type(s2) # s2's type has changed.
<class '_example.Spam'>
>>> example.fun('ghi')
fun() -> Spam::action(): ghi

请注意,上例中的帧操作仅修改fun()的调用者的框架而不是整个堆栈。

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

Boost.python自动转换参数 的相关文章

  • pandas to_sql sqlalchemy 与 secure_transport 的连接

    我正在尝试将数据发送到具有 require secure transport ON 的服务器上的 mysql 数据库 当我尝试使用以下代码连接到它时 import pandas as pd import pymysql from sqlal
  • 根据给定列表中的值替换列中的值[重复]

    这个问题在这里已经有答案了 我在数据框中有一列 仅允许定义列表中存在的值 例如 给定列表 l1 1 2 5 6 如果列表中不存在列中的值 我需要将每个值替换为 0 column Expected column 1 1 5 5 2 2 3 0
  • ASP.NET:获取自 1970 年 1 月 1 日以来的毫秒数

    我有一个 ASP NET VB NET 日期 我试图获取自 1970 年 1 月 1 日以来的毫秒数 我尝试在 MSDN 中寻找方法 但找不到任何东西 有谁知道如何做到这一点 从 NET 4 6 开始 该方法ToUnixTimeMillis
  • 如何在 Linq 中获得左外连接?

    我的数据库中有两个表 如下所示 顾客 C ID city 1 Dhaka 2 New york 3 London 个人信息 P ID C ID Field value 1 1 First Name Nasir 2 1 Last Name U
  • 使用 Python 脚本打开特定文件类型?

    如何使 Python 脚本成为特定文件类型 例如 foo 的默认应用程序 例如 当我双击 Finder Explorer 中的文件时 我希望该文件在 Python 脚本中打开 这可以在 Win 和 或 OS X 中实现吗 如果重要的话 该应
  • 如何使用 watin 中的 FileUploadDialogHandler 访问文件上传对话框

    我正在使用 IE8 和 watin 并尝试通过我的网页测试上传文件 我不能简单地使用 set 方法设置上传文件 例如 ie FileUpload Find ById someId Set C Desktop image jpg 因为上传文本
  • 使用 statsmodels.formula.api 中的 ols - 如何删除常数项?

    我正在遵循第一个例子statsmodels教程 http statsmodels sourceforge net devel http statsmodels sourceforge net devel 如何指定在 ols 中不使用常数项进
  • 等待线程完成

    private void button1 Click object sender EventArgs e for int i 0 i lt 15 i Thread nova new Thread Method nova Start list
  • 如何将 fields 参数传递到 Google Drive Python API 调用中

    I have results drive service files list body execute where body q query string maxResults 1 为了提高性能 我想限制返回的字段 如下所述 https
  • 如何从main方法调用业务对象类?

    我已将代码分为业务对象 访问层 如下所示 void Main Business object public class ExpenseBO public void MakeExpense ExpensePayload payload var
  • Pip 突然使用了错误版本的 Python

    在 os x 上使用 pip 时遇到一个奇怪的问题 据我所知 快速查看我的 bash history 似乎可以确认 我最近没有对我的配置进行任何更改 唉 pip 命令似乎突然使用了与以前不同的 python 版本 到目前为止 我使用命令 p
  • C++ 密码屏蔽

    我正在编写一个代码来接收密码输入 下面是我的代码 程序运行良好 但问题是除了数字和字母字符之外的其他键也被读取 例如删除 插入等 我知道如何避免它吗 特q string pw char c while c 13 Loop until Ent
  • Flask 扩展未在 app.extensions 中注册

    我想访问在我的 Flask 应用程序上注册的一些扩展 我尝试使用app extensions 但我初始化的一些扩展不在字典中 from flask import current app current app extensions get
  • 如何在 C# 中调整图像大小同时保持高质量?

    我从这里找到了一篇关于图像处理的文章 http www switchonthecode com tutorials csharp tutorial image editing saving cropping and resizing htt
  • 有没有办法强制显示工具提示?

    我有一个验证字段的方法 如果无法验证 该字段将被清除并标记为红色 我还希望在框上方弹出一个工具提示 并向用户显示该值无效的消息 有没有办法做到这一点 并且可以控制工具提示显示的时间 我怎样才能让它自己弹出而不是鼠标悬停时弹出 If the
  • 英特尔 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
  • 当另一个线程可能设置共享布尔标志(最多一次)时,是否可以读取共享布尔标志而不锁定它?

    我希望我的线程能够更优雅地关闭 因此我尝试实现一个简单的信号机制 我不认为我想要一个完全事件驱动的线程 所以我有一个工作人员有一种方法可以使用关键部分优雅地停止它Monitor 相当于C lock我相信 绘图线程 h class Drawi
  • 如何使用 Word Automation 获取页面范围

    如何使用办公自动化找到 Microsoft Word 中第 n 页的范围 似乎没有 getPageRange n 函数 并且不清楚它们是如何划分的 这就是您从 VBA 执行此操作的方法 转换为 Matlab COM 调用应该相当简单 Pub
  • 在客户端系统中安装后桌面应用程序无法打开

    我目前正在使用 Visual Studio 2017 和 4 6 1 net 框架 我为桌面应用程序创建了安装文件 安装程序在我的系统中完美安装并运行 问题是安装程序在其他计算机上成功安装 但应用程序无法打开 edit 在客户端系统中下载了

随机推荐

  • 猫鼬鉴别器在数据库中有何帮助? [关闭]

    Closed 这个问题需要多问focused 目前不接受答案 你好 我正在学习 mongodb 我了解了 mongoose 中的鉴别器 我试图从文档方面理解它 但不太理解 任何人都可以用更好的方式解释吗 谢谢 举个例子 您的项目有两个角色
  • 图像和其他 div 彼此相邻的 Div 容器 [关闭]

    很难说出这里问的是什么 这个问题模棱两可 含糊不清 不完整 过于宽泛或言辞激烈 无法以目前的形式合理回答 如需帮助澄清此问题以便重新打开 访问帮助中心 我正在尝试绘制一个容器 其中包含左侧的图像 缩略图 和图像旁边的几个 div 垂直 在容
  • 检查多维数组中是否存在特定的数组键 - PHP

    我有一个多维数组 例如 这可能有很多层次 array Array 21 gt Array 24 gt Array 22 gt Array 25 gt Array 26 gt Array 我试图循环它以查看某个键是否存在 keySearch
  • NVD3 中的 ScatterChart – 从 csv 文件读取数据

    我正在尝试从 csv 文件读取数据 并希望使用 NVD3 中的 scatterChart 来可视化该数据 我会链接到 JSfiddle 或类似的东西 但我不知道如何在这些在线 JavaScript IDE 中包含 csv 文件 那可能吗 c
  • 分割字符串,然后显示没有最后一个的所有项目

    我有 例如 字符串let abc Jonny Name 所以如果我想检查 这是不是名字 我会检查 let isName abc split 1 isName Name your name is abc split 0 not name 但我
  • 同一服务器上的多个 Mongodb 实例

    我正在使用 Mongo DB 但我是它的新手 我准备将它安装在专门用于 Mongo 的服务器上 我想创建它的 2 个实例 1 个用于支持 QA 环境 另一个用于支持临时环境 我更熟悉 SQL Server 我可以在其中创建多个实例 是否可以
  • 在 CLI 中生成随机 BMP

    我需要一个真正随机的 BMP 来测试各种有损图像压缩算法 理想情况下 这不会依赖于任何库并在 Linux CLI 中运行 它应该生成一个随机的 BMP 给定一定的width and height 更新答案 2021 年 4 月 以下是关于随
  • 如何使用 LWP::Simple 处理代理服务器?

    如何向该脚本添加代理支持 use LWP Simple url http stackoverflow com word how to ask content get url if content m word print Found wor
  • 如何从电子表格公式调用库函数作为自定义函数?

    这可能是与以下相同的根本原因如何从同一库生成的电子表格下拉菜单中调用库函数 但我仍然想把它扔掉 以防出现新的情况或情况有所不同 问题是我想将所有自定义函数保留在一个库中 然后将该库添加到任何给定的电子表格中 并能够从单元格公式中引用它们 在
  • iOS UICollectionView:具有交替网格对齐方式的圆形视图的单元格

    我正在尝试实施UICollectionView用于圆形的自定义单元格 现在 默认情况下 圆的对齐方式与普通方形单元格相同 顶部圆和底部圆位于同一垂直线上 如何将对齐更改为 顶部圆和其下面的两个圆形成等边三角形 顶部圆和底部圆的位置按半径长度
  • 使用 React Route 部署到 S3 后看到空白页面

    我使用 React 和 React Router 构建了 SPA 我也在用https github com facebookincubator create react app因为它是一个非常简单的应用程序 当我使用 webpack 进行开
  • Java - 使用 ImageIO 进行多线程处理

    我有一个程序加载缓慢 我猜这是由于我一开始必须加载的图像资源量所致 我认为多线程会有所帮助 但现在我不太确定 这是我的自动多线程方法 private static Thread t private static int currentThr
  • 为什么 printf 在终端中显示额外的 % 字符?

    我开始学习用 C 语言编写代码 我写了以下程序 include
  • 替换字符组合

    我有一根绳子27AAGCB5913L2ZF 如果有任何一个A or J or K出现在字符串中 那么我需要将它们更改为这三个字母的所有可能组合 如果我将上面的字符串输入传递给程序 那么输出应该是这样的 27AAGCB5913L2ZF 27A
  • 消费者阅读 __consumer_offsets 传递不可读的消息

    我正在尝试从 consumer offsets 主题进行消费 因为这似乎可能是检索有关消费者的 kafka 指标 例如消息延迟等 的最简单方法 理想的方法是从 jmx 访问它 但想先尝试一下 返回的消息似乎被加密或以不可读的形式 也尝试添加
  • 如何在 Laravel 中实现我的 sql 语句?

    我有以下 MySQL 查询 效果很好 它从我的表中返回随机结果 SET prev 0 rownum 0 SELECT utilizador id nome FROM SELECT IF prev lt gt utilizador id ro
  • 两个命名空间之间的不明确引用错误

    我在尝试在浏览器上运行 Web 服务时收到此消息 请注意 源代码是一个 Windows 文件 无法根据我的需要进行更改 编译器错误消息 CS0104 消息 是不明确的引用 在 ThreeDSeekUtils Message 和之间 Syst
  • 如何用javascript制作一个简单的自动播放幻灯片?

    我想制作一个简单的幻灯片放映 在页面加载时自动播放 到目前为止 这是我的代码 HTML div div img src slide 1 png div div img src slide 2 png div div img src slid
  • 使用install_github时出错:'exdir'不存在

    我正在尝试从 github 安装软件包 但不断收到以下错误 Error in unzip src list TRUE exdir does not exist 我猜测 unzip 无权创建要解压缩的目录 但我不知道如何将参数传递给 exdi
  • Boost.python自动转换参数

    我正在使用 boost python 来包装 C 类 A 该类采用字符串作为构造函数 然后我有一个函数 fun A arg 它将引用 A 作为参数 我想要一个 fun 的Python包装器 如果我传递一个对Python字符串的引用的变量 这