2016-09-28 155 views
1

我有一个C++实现,用SWIG包装并编译为一个可以被python使用的模块。将ctypes int **转换为numpy 2维数组

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

我怎样才能把这个变成一个2D numpy数组在Python脚本内?我一直在看ctypes指针,但到目前为止我没有运气。我已经花了很多很多时间阅读Python的C-API和numpy以用于SWIG,并且在C++端实现返回一个numpy数组迄今非常困难并且完全不成功。

+0

看起来像一个重复的SWIG作出生成的代码。这个答案呢? http://stackoverflow.com/questions/22425921/pass-a-2d-numpy-array-to-c-using-ctypes –

+0

这个问题似乎是这个问题的双重性,@TheQuantumPhysicist(numpy - > int ** ,而不是int ** - > numpy) – Eric

+0

int **是动态分配的吗? “删除[]”的工作是谁的? – Eric

回答

0

我不认为这可以在Python方面完成;它必须在C/C++层使用NumPy的C-API接口完成(PyArray_SimpleNewFromData是相关功能 - 有关详细信息,请参见this answer)。 Here是Cython脚本中的一个例子。

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

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

+0

这绝对可以在python一方完成(ctypes为您提供了取消引用指针所需的所有机制),但您说得对,numpy仅适用于连续的数据缓冲区。当然,这是可能的(但不太可能)数据是连续的 – Eric

+0

我明白ctypes可以让你操作指针,但我认为你不能在Python方面调用numpy的''PyArray_SimpleNewFromData''(尽管我会很高兴被证明是错误的!) – jakevdp

+0

我认为[这个问题](https:// stackoverflow。com/questions/4355524/getting-data-from-ctypes-array-into-numpy)解决了一维情况,并且由于数据无论如何都是不相交的,这是您可以做的最好的。 – Eric

0

使用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" 

的吨ypemap ARGOUTVIEWM_ARRAY2创建一个托管的NumPy数组,当NumPy对象在Python中销毁时,自动调用free。

如果你想创建使用Python C API自己的包装,你可以考虑使用numpy.i