将 ctypes int** 转换为 numpy 二维数组

Posted

技术标签:

【中文标题】将 ctypes int** 转换为 numpy 二维数组【英文标题】:Convert a ctypes int** to numpy 2 dimensional array 【发布时间】:2016-09-28 09:32:09 【问题描述】:

我有一个用 SWIG 包装的 c++ 实现,并编译成一个可供 python 使用的模块。

我正在使用 ctypes 来调用带有 ctype 参数、int double 等的函数。 my_function(ctype args) 的输出是一个int**,即它是一个多维数组。

如何在 python 脚本中将其转换为 2D numpy 数组?我一直在看 ctypes 指针,但到目前为止我还没有运气。我花了很多很多时间阅读 python 和 numpy 的 C-API 以与 SWIG 一起使用,并且在 c++ 端实现返回一个 numpy 数组迄今为止非常困难并且完全不成功。

【问题讨论】:

看起来像复制品。这个答案呢? ***.com/questions/22425921/… 这个问题似乎是这个问题的双重性,@TheQuantumPhysicist (numpy -> int**, not int** -> numpy) int** 是动态分配的吗? delete []它是谁的工作? "int**,即它是一个多维数组" - 不成立。指针不是数组。它可以指向一个数组,但它也可以指向单个项目或什么都没有。 int i; int* ip = &i; int** ipp = &ip; 【参考方案1】:

我认为这不能在 Python 端完成;它必须使用 NumPy 的 C-API 接口在 C/C++ 层内完成(PyArray_SimpleNewFromData 是相关函数 - 有关详细信息,请参阅 this answer)。 Here 是 Cython 脚本中的一个示例。

请注意,在这种情况下,解除分配的处理很复杂:据我所知,没有机制允许 numpy 自动处理它。您只需要确保当 numpy 包装器仍在使用时,无论脚本解除分配数组都不会这样做。

编辑:如果您的 int** 没有指向连续的内存块,我不相信这会起作用。 NumPy 只能(轻松)处理连续的数据缓冲区。

【讨论】:

这绝对可以在 python 端完成(ctypes 为您提供取消引用指针所需的所有机制),但您说 numpy 仅适用于连续数据缓冲区是正确的。当然,数据有可能(但不太可能)是连续的 我知道 ctypes 可以让你操纵指针,但我认为你不能从 Python 端调用相当于 numpy 的 PyArray_SimpleNewFromData (尽管我很高兴被证明是错误的!) 我认为this question 解决了 1D 的情况,而且由于数据无论如何都是不相交的,这是你能做的最好的。【参考方案2】:

使用 NumPy 和 numpy.i,这很容易

接口头

#pragma once
void fun(int** outArray, int* nRows, int* nCols);

实施

#include "test.h"
#include <malloc.h>
void fun(int** outArray, int* nRows, int* nCols) 
  int _nRows = 100;
  int _nCols = 150;
  int* _outArray = (int*)malloc(sizeof(int)*_nRows*_nCols);
  *outArray = _outArray;
  *nRows = _nRows;
  *nCols = _nCols;

SWIG 接口头

%module example
%
  #define SWIG_FILE_WITH_INIT
  #include "test.h"
%

%include "numpy.i"

%init
%
  import_array();
%

%apply (int** ARGOUTVIEWM_ARRAY2, int* DIM1, int* DIM2) (int** outArray, int* nRows, int* nCols)
%include "test.h"

typemap ARGOUTVIEWM_ARRAY2 创建一个托管 NumPy 数组并在 Python 中销毁 NumPy 对象时自动调用 free。

如果您想使用 Python C API 自己创建包装器,可以查看 SWIG 使用 numpy.i 生成的代码

【讨论】:

以上是关于将 ctypes int** 转换为 numpy 二维数组的主要内容,如果未能解决你的问题,请参考以下文章

如何将 ctypes 的 c_long 转换为 Python 的 int?

使用 ctypes 从 C 结构数组到 NumPy 数组的高效转换

Tensorflow TypeError:无法将'numpy.int64'对象隐式转换为str

如何将 2D float numpy 数组转换为 2D int numpy 数组?

如何使用 SWIG 将 numpy 数组转换为 vector<int>&(参考)

自己的数据集:ValueError:无法将 NumPy 数组转换为张量(不支持的对象类型 int)