当 import_array 不在同一翻译单元中时出现段错误

2023-11-25

我在正确初始化 NumPy C API 时遇到问题。我想我已经将问题与调用隔离了import_array来自不同的翻译单位,但我不知道为什么这很重要。

最小工作示例:

header1.hpp

#ifndef HEADER1_HPP
#define HEADER1_HPP
#include <Python.h>
#include <numpy/npy_3kcompat.h>
#include <numpy/arrayobject.h>

void initialize();

#endif

文件1.cpp

#include "header1.hpp"

void* wrap_import_array()
{
  import_array();
  return (void*) 1;
}

void initialize()
{
  wrap_import_array();
}

文件2.cpp

#include "header1.hpp"

#include <iostream>

void* loc_wrap_import_array()
{
  import_array();
  return (void*) 1;
}

void loc_initialize()
{
  loc_wrap_import_array();
}

int main()
{
  Py_Initialize();
#ifdef USE_LOC_INIT
  loc_initialize();
#else
  initialize();
#endif
  npy_intp dims[] = {5};
  std::cout << "creating descr" << std::endl;
  PyArray_Descr* dtype = PyArray_DescrFromType(NPY_FLOAT64);
  std::cout << "zeros" << std::endl;
  PyArray_Zeros(1, dims, dtype, 0);
  std::cout << "cleanup" << std::endl;
  return 0;
}

编译命令:

g++ file1.cpp file2.cpp -o segissue -lpython3.4m -I/usr/include/python3.4m -DUSE_LOC_INIT
./segissue
# runs fine

g++ file1.cpp file2.cpp -o segissue -lpython3.4m -I/usr/include/python3.4m
./segissue
# segfaults

我已经使用 Clang 3.6.0、GCC 4.9.2、Python 2.7 和 Python 3.4(经过适当修改)进行了测试wrap_import_array因为 Python 2.x 和 3.x 之间这是不同的)。各种组合都给出相同的结果:如果我不打电话loc_initialize,程序将出现段错误PyArray_DescrFromType称呼。我有 NumPy 版本 1.8.2。作为参考,我在 Ubuntu 15.04 中运行它。

最令我困惑的是这个 C++ NumPy 包装器似乎没有打电话import_array在不同的翻译单元中。

我缺少什么?为什么我必须打电话import_array来自同一个翻译单元才能使其真正生效?更重要的是,当我打电话时如何让它工作import_array来自不同的翻译单元,如 Boost.NumPy 包装器?


在深入研究 NumPy 标头后,我想我找到了解决方案:

in numpy/__multiarray_api.h,有一节讨论内部 API 缓冲区应该在哪里。为了简洁起见,以下是相关片段:

#if defined(PY_ARRAY_UNIQUE_SYMBOL)
#define PyArray_API PY_ARRAY_UNIQUE_SYMBOL
#endif

#if defined(NO_IMPORT) || defined(NO_IMPORT_ARRAY)
extern void **PyArray_API;
#else
#if defined(PY_ARRAY_UNIQUE_SYMBOL)
void **PyArray_API;
#else
static void **PyArray_API=NULL;
#endif
#endif

看起来这是为了允许多个模块定义自己的内部 API 缓冲区,其中每个模块必须调用自己的import_array define.

让多个翻译单元使用相同内部 API 缓冲区的一致方法是在每个模块中定义PY_ARRAY_UNIQUE_SYMBOL某个库的唯一名称,然后每个翻译单元除了定义 import_array 包装器的包装器之外定义NO_IMPORT or NO_IMPORT_ARRAY。顺便说一句,ufunc 功能也有类似的宏:PY_UFUNC_UNIQUE_SYMBOL, and NO_IMPORT/NO_IMPORT_UFUNC.

修改后的工作示例:

header1.hpp

#ifndef HEADER1_HPP
#define HEADER1_HPP

#ifndef MYLIBRARY_USE_IMPORT
#define NO_IMPORT
#endif

#define PY_ARRAY_UNIQUE_SYMBOL MYLIBRARY_ARRAY_API
#define PY_UFUNC_UNIQUE_SYMBOL MYLIBRARY_UFUNC_API

#include <Python.h>
#include <numpy/npy_3kcompat.h>
#include <numpy/arrayobject.h>

void initialize();

#endif

文件1.cpp

#define MYLIBRARY_USE_IMPORT
#include "header1.hpp"

void* wrap_import_array()
{
  import_array();
  return (void*) 1;
}

void initialize()
{
  wrap_import_array();
}

文件2.cpp

#include "header1.hpp"

#include <iostream>

int main()
{
  Py_Initialize();
  initialize();
  npy_intp dims[] = {5};
  std::cout << "creating descr" << std::endl;
  PyArray_Descr* dtype = PyArray_DescrFromType(NPY_FLOAT64);
  std::cout << "zeros" << std::endl;
  PyArray_Zeros(1, dims, dtype, 0);
  std::cout << "cleanup" << std::endl;
  return 0;
}

我不知道这个黑客有什么陷阱,或者是否有更好的替代方案,但这似乎至少编译和运行没有任何段错误。

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

当 import_array 不在同一翻译单元中时出现段错误 的相关文章

随机推荐

  • 用于处理文件路径的 Qt 类[重复]

    这个问题在这里已经有答案了 可能的重复 Qt 相当于 PathAppend Qt 中有处理文件路径的类吗 特别是我正在寻找像 NET 的 Path Combine 这样的东西 我知道 boost filesystem 中有一个 但我想知道
  • Scala 开关在成功匹配后继续匹配下一个案例

    我该如何在 scala switch 语句中执行一个 case 块后开始执行另一个 case 块 在java中 没有中断的情况 switch step case 0 do something case 1 do something more
  • .dll 文件无法访问

    我正在尝试将 dll 添加到我的项目中 当我 添加引用 并尝试添加它时 它告诉我 无法添加对 的引用 请确保该文件 可访问 并且它是有效的程序集或 COM 组件 顺便说一句 我正在尝试添加 g729 dll 我怎样才能添加dll 你必须re
  • 垂直进度条

    VS 2005 SP3 我曾多次使用进度条 但是 我需要一个垂直的 但是 我找不到任何可以旋转它的属性 进度条是否始终处于水平位置且无法更改 非常感谢 尝试这个 public class VerticalProgressBar Progre
  • PHP 和 MySQL 之间的周数差异

    我有以下查询 SELECT COUNT WEEK date YEAR date FROM myTable GROUP ON YEAR date WEEK date 假设它产生以下结果 32 33 2012 43 34 2012 39 35
  • 将彩色控制台输出捕获到 WPF 应用程序中

    如同这个问题 除了 WPF 应用程序中包含的控制台程序会生成彩色输出 因此如果我能够捕获颜色和文本 那就太好了 这是我的第一个 WPF 程序 我不知道如何查找 修改正确的控件 目前我只是使用一个 TextBox 它可以工作 但只能捕获纯文本
  • 如何配置 Geany 来编译和运行我的 Python 程序?

    在 构建 菜单下 我可以看到 执行 选项 但它是灰色的 唯一可用的选项是 设置包含和参数 当我单击时 两个字段都已填写 我必须在那里写什么 I don t need to configure anything in Geany I just
  • 寻找一种使用 NSArray 作为一堆按钮的插座的方法

    我的用户界面有四个按钮 它们都会共享一些共同的行为 例如跟踪区域创建之类的事情 我正在寻找的是一个解决方案 所以我不必这样做 interface MyController NSWindowController NSButton button
  • 带有选项卡和 Viewpager 的 Android Fragments

    我们正在构建一个如上所示的具有片段嵌套的应用程序 选项卡特色 详细信息选项卡和地图选项卡 详细信息选项卡将有一个幻灯片 就像 查看页面滑块 和下面可滚动的信息 地图选项卡将显示地图 我已经实现了选项卡 地图以及滑块 如上所示 现在我很困惑如
  • 通过 AcceptEx() 连接的套接字的 TCP 关闭

    的文档AcceptEx says 当此操作成功完成后 sAcceptSocket 可以 已通过 但仅限以下功能 ReadFile 写文件 send WSASend recv WSARecv 传输文件 封闭式插座 setsockopt 仅适用
  • 为什么 Tensorflow-gpu 仍然使用 cpu

    我在后端使用带有tensorflow gpu的Keras 我没有安装tensorflow CPU版本 所有输出都显示选择了GPU 但tf正在使用CPU和系统内存 当我运行代码时 输 出是 输出代码 我什至运行了 device lib lis
  • 使用 matlabpool 时出错 - 未定义函数“distcomp.fileserializer”

    我正在尝试使用 MATLAB 中的并行计算工具箱来帮助加速我正在执行的一些密集计算 在我可以使用像这样的结构之前parfor 我需要通过创建一个工人池matlabpool 首先 我只想使用默认的 local只需调用即可配置文件matlabp
  • 应用程序沙盒/iCloud 和 Snow Leopard 向后兼容性

    到目前为止 所有 Mac App Store 开发人员都知道 所有应用程序都必须启用新的 OSX Lion Sandboxing 对于现有应用程序 我们必须在 XCode 4 2 中启用它并设置数据迁移 plist 因此 我现有的 Mac
  • Java 中“new”关键字的实际作用是什么?我应该避免创建新对象吗?

    我不久前注册了 尽管自从我开始自学计算机编程以来 我一直在充分利用这个网站 我一直在自学计算机编程 并认为这是我的一个小爱好 我确实查找过类似的问题 但事实上我找不到我正在寻找的答案 现在 请注意 在 Java 这是我建议开始使用的语言 中
  • 使用 package.json 全局和本地安装依赖项

    使用 npm 我们可以使用以下命令全局安装模块 g选项 我们如何在 package json 文件中执行此操作 假设 这些是我在 package json 文件中的依赖项 dependencies mongoose 1 4 0 node i
  • 日期字段在验证时给出所需的错误

    我在我的 asp net MVC 3 网站中创建了一个模型 并有一个名为 DateOpened 的属性 Column Date Opened Display Name Date Opened DataType DataType Date D
  • Android Fragment 导航和 Backstack

    我有一个标题栏 有点像菜单 和 4 个片段 MAIN A B C 其中 MAIN 应该是用于 backstack 的 main root 片段 我遇到的问题是当用户通过菜单进入例如 MAIN gt A gt B gt C 时 如果我只是使用
  • Android Studio 无法找到有效的 Jvm(与 MAC OS 相关)

    我无法在 Mac OS 10 10 1 Yosemite 上启动 Android Studio 进行 Android 开发 打开应用程序包安卓工作室在 Finder 中 然后编辑信息表文件 更改关键 JVM 版本 将 1 6 改为 1 6
  • CMake:如何为头文件设置COMPILE_FLAGS?

    我已经成功使用CMake构建了共享库 但大小不太好 我已经尝试过几个编译标志来减少大小等 set source files properties TARGET SOURCE FILES PROPERTIES COMPILE FLAGS fe
  • 当 import_array 不在同一翻译单元中时出现段错误

    我在正确初始化 NumPy C API 时遇到问题 我想我已经将问题与调用隔离了import array来自不同的翻译单位 但我不知道为什么这很重要 最小工作示例 header1 hpp ifndef HEADER1 HPP define