Boost Python 1.48 在导出 32 位枚举时失败

2023-12-04

较新版本的 Boost Python 是否支持从 C++ 导出完整的 32 位枚举?我使用的是 1.48,并且能够导出最多 30 位,但当我尝试导出 32 位数字时,由于“访问冲突读取位置 0x00000001”,每次都会失败。深入研究 enum.cpp 文件,发现当创建对象 x 时,它将字节 20 设置为 1,这会在稍后尝试在 p->name 存在之前递减 p->name 时导致失败。我是否只需要升级到较新版本的 boost python 还是无法导出完整的 32 位数字?感谢您的输入!


EDIT:由 Tigger 在工作中发现,在此记录以供后代使用:

问题在于 enum_object 结构的定义。 base_object 中的底层数字存储允许 15 位数字(作为 Shorts)或 30 位数字(作为 int)粒度,但 base_object 仅包含足够的空间用于 2x 15 位数字或 1x 30 位数字。当存储 > 30 位枚举值时,编码需要 3 个短整型或 2 个整型,具体取决于编译的格式。结果是名称成员占用了额外数字存储所需的空间。引用递减失败,因为该值被放置在名称成员期望的位置。

解决方案是添加at least名称成员之前的 32 位填充用于处理 32 位枚举值。如果在遥远的将来需要 64 位枚举,则应添加 2 个填充字。

struct enum_object
{
#if PY_VERSION_HEX >= 0x03000000
   PyLongObject base_object;
#else
   PyIntObject base_object;
#endif
   // ADD PADDING HERE TO FIX ALIGNMENT ISSUE
   PyObject* name;
};

END EDIT

TL/DR:根本错误要么是在转换中,要么是通过 enum_base::add_value 函数的堆栈变量进行假定的对象对齐,但最简单的方法可能是单步执行转换器以查看该值是否以某种方式被破坏。我尝试的另一个实验是交换 .value 调用的顺序(这可能有助于确定是否存在与堆栈相关的问题)。

详细信息: enum_base::add_value 函数在 1.48 和 1.58(最新)之间保持不变。此外,基于 python::api::object 类和 object_base_initializer 模板的显式转换“(*this)(value)”似乎也没有改变。我没有进一步遍历 object_base 构造函数来查看那里是否有任何变化;我建议使用有问题的值逐步执行转换序列,看看高两位是否发生任何异常情况(我不确定您会在那里找到任何东西,但值得检查)。

请记住,转换后的值随后被复制到堆栈“object x = (this)(value);" 以及 enum_object 的向下转型p 覆盖的对象大于 x.ptr() 引用的对象(即 m_ptr 成员)。我现在不确定 m_p​​tr 是堆栈还是堆(没有遍历这些细节),但无论哪种方式,如果 p 现在覆盖陈旧或未初始化的内存,那么 p->name 处的引用递减将失败(如果不是)指向有效的内存(如您所发现的)。

我不确定 p->name 引用递减是否必要(对象生存期是本地的)...我必须再考虑一下。我们可以在周一讨论更多...这是周末...休息一下(就像我应该说话一样!)

void enum_base::add_value(char const* name_, long value)
{
    // Convert name to Python string
    object name(name_);

    // Create a new enum instance by calling the class with a value
    object x = (*this)(value);

    // Store the object in the enum class
    (*this).attr(name_) = x;

    dict d = extract<dict>(this->attr("values"))();
    d[value] = x;

    // Set the name field in the new enum instanec
    enum_object* p = downcast<enum_object>(x.ptr());
    Py_XDECREF(p->name);
    p->name = incref(name.ptr());

    dict names_dict = extract<dict>(this->attr("names"))();
    names_dict[x.attr("name")] = x;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Boost Python 1.48 在导出 32 位枚举时失败 的相关文章

随机推荐

  • Ctor Initializer:自初始化导致崩溃?

    我很难调试生产中的崩溃 只是想与这里的人们确认语义 我们有一堂课 比如 class Test public Test members initialized m str m str Test private other members st
  • 如何阻止恶意代码欺骗“Origin”标头来利用 CORS?

    按照我的理解 如果在 foo com 页面上运行的客户端脚本想要从 bar com 请求数据 则在请求中它必须指定标头Origin http foo com 并且 bar 必须响应Access Control Allow Origin ht
  • 在 Linux 上安装 Rglpk

    我正在尝试使用 install packages 命令安装 Rglpk 我收到此错误 bin sh 第 0 行 cd GLPK 没有这样的文件或目录 make GLPK ts 错误 1 glpk dev 软件包已安装 rpm qa grep
  • 私有[this] 与私有

    在 Scala 中 我看到了对象私有变量这样的功能 从我不太丰富的 Java 背景中 我学会了关闭所有内容 使其私有 并在必要时打开 提供访问器 Scala 引入了更严格的访问修饰符 我应该始终默认使用它吗 或者我应该仅在某些特定情况下使用
  • 什么是 WindowInsets?

    我正在尝试了解 Android 操作系统 当我阅读 Google I O 2014 应用程序时 我遇到了WindowInsets 如果有人可以解释它们是什么 那么这将是一个很大的帮助 谢谢 WindowInsets是应用于窗口的系统视图 例
  • python 子类化:TypeError object.__new__() 不带参数

    好吧 我又被难住了 不过这应该很容易 我正在尝试对 pytables 类进行子类化tables IsDefinition 如下 import tables class doc tables IsDescription def init se
  • {Java} Vaadin 14 - 检测用户离开(关闭选项卡、f5 等)

    我目前正在使用Vaadin 流版本 14 https github com vaadin platform releases tag 14 0 0 我运行 Java 版本 1 8 0 231 64 位 我只是希望能够检测 在 java 中
  • 我正在尝试将多个蜘蛛的结果存储到 MySQL 中的单独表中

    这是我的 pipelines py 我有两只蜘蛛 一只叫 bristol py 一只叫 Bath py 当我运行 scrapycrawl bristol 时 它会自动将结果添加到名为 Bristol 的 MySQL 数据库表中 我想运行 s
  • 扫描特定服务 CBUUID 时找不到外围设备

    当我使用时 CBUUID uuid CBUUID UUIDWithString 1800 GAP DEBUG LOG CBUUID uuid CBUUID Generic Access Profile centralMan CBCentra
  • Delphi - 在运行时解析 JSON 数据时发生访问冲突

    我是论坛新手 如果我的帖子格式不正确或未遵循指南 请深表歉意 我会很快 得到 这是我的问题 看看下面的代码 我已经删除了几乎所有无关的部分 以将注意力集中在一个关键行上 LParts LJsonObj Get parts JsonValue
  • Cocoa应用程序系统重启

    您知道有什么方法可以通过代码强制重新启动 Mac OS 计算机吗 我尝试了一个小的 applescript 代码 但没有结果 应用程序要求用户关闭 以便用户可以停止重新启动过程 Regards 官方的方式是向登录窗口进程发送系统事件 苹果技
  • 如何在 C# Windows 窗体应用程序中的数据 gridview 中进行搜索?

    我有一个表单 其中一个简单的 gridview 由数据库中的表填充 其中包含 TicketID 名称 公司 产品等列 现在我想添加搜索功能 以便用户可以按客户名称或公司或 TicketID 进行搜索 我怎样才能做到这一点 我想在数据网格上方
  • 使用来自 URL 列的 importXML 和 arrayformula 在 google 工作表中返回相同的重复结果

    我已成功使用 ImportXML 获取 Youtube 视频的标题以及 Google Sheets 中的 URL 这是我的代码 IF ISBLANK A3 A IMPORTXML A3 A id eow title 但是 当我尝试在 Imp
  • 机架 ssl 不适用于 Thin

    我按照以下说明为 Rails 3 07 安装了rack ssl http www simonecarletti com blog 2011 05 configuring rails 3 https ssl 它不起作用 发出第一个 https
  • 快速比较两个结构的值

    我有两个结构体和两个与之对应的数组 我试图比较这两个数组值并将其打印在一个过滤数组中我确实尝试过使用过滤器 但它给了我一个错误我想比较结构体和获取一个数组 结构一 struct One let ID String let name Stri
  • 由于警告和 ValueError,无法在 Windows 的 virtualenv 中 pip 安装 PIL

    我正在尝试安装PIL在 virtualenv 中但失败了 我创建了一个全新的 virtualenv 并做了pip install PIL并得到以下结果 C Users s3z Desktop My Dropbox pythons ham g
  • 计算 iOS 中的电池寿命

    想知道除了苹果技术统计数据之外是否还有其他参考资料来计算电池寿命 我尝试比较一些现有的电池应用程序 剩余电池百分比 苹果的数据 但有时我没有得出相同的答案 另外还有使用 2G 电池 而不是 3G 的统计数据 我在 Apple 上没有看到任何
  • 如何为另一个使用 stdin 输入的函数编写测试函数?

    作为大学作业的一部分 我有以下职能 int readMenuOption local declarations char option 2 read in 1 char from stdin plus 1 char for string t
  • 播放音频并继续播放

    我正在用 C 在 unity 5 中制作一个小游戏 到目前为止 我已经成功设计了关卡并完成了一些基本的脚本编写 目前 我有一个触发器 可以生成一个对象 并希望它在用户输入后播放并播放音频源 然而 因为我希望它是一个跳跃恐慌 所以触发器非常小
  • Boost Python 1.48 在导出 32 位枚举时失败

    较新版本的 Boost Python 是否支持从 C 导出完整的 32 位枚举 我使用的是 1 48 并且能够导出最多 30 位 但当我尝试导出 32 位数字时 由于 访问冲突读取位置 0x00000001 每次都会失败 深入研究 enum