2016-09-28 2 views
1

Ich habe eine C++ - Implementierung mit SWIG umwickelt und kompiliert zu einem Modul, das von Python verwendet werden kann.Konvertiere ein Ctypes int ** in ein numpiges zweidimensionales Array

Ich benutze Ctypes, um die Funktion mit ctype Argumente, int double etc. Die Ausgabe von my_function (ctype args) ist ein int **, d. H. Es ist ein mehrdimensionales Array.

Wie kann ich dies in ein zweidimensionales Array innerhalb des Python-Skripts umwandeln? Ich habe mir Ctypes-Zeiger angesehen, aber bisher hatte ich kein Glück. Ich habe viele, viele Stunden damit verbracht, die C-API von Python und Numpy für die Verwendung mit SWIG zu lesen, und die Implementierung auf der C++ - Seite, um ein numpiges Array zurückzugeben, war bisher unglaublich hart und völlig erfolglos.

+0

wie ein Duplikat Looks. Was ist mit dieser Antwort? http://stackoverflow.com/questions/22425921/pass-a-2d-numpy-array-to-c-using-ctypes –

+0

Diese Frage scheint die Dual zu diesem, @TheQuantumPhysicist (numpy -> int **) , nicht int ** -> numpy) – Eric

+0

Ist das 'int **' dynamisch zugewiesen? Wessen Aufgabe ist es, es zu löschen? – Eric

Antwort

0

Ich glaube nicht, dass dies auf der Python-Seite getan werden kann; es muss innerhalb der C/C++ - Schicht mit der C-API-Schnittstelle von NumPy geschehen (PyArray_SimpleNewFromData ist die relevante Funktion - siehe this answer für einige Details). Here ist ein Beispiel dafür in einem Cython-Skript.

Beachten Sie, dass die Handhabung der Freigabe in diesem Fall kompliziert ist: Soweit ich weiß, gibt es keinen Mechanismus, der es numpy erlaubt, es automatisch zu verarbeiten. Sie müssen nur sicherstellen, dass das Skript, das das Array freigibt, dies nicht tut, wenn der numpige Wrapper noch verwendet wird.

Edit: Wenn Ihr int** nicht auf einen zusammenhängenden Speicherblock zeigt, glaube ich nicht, dass dies funktioniert. NumPy kann nur (einfach) zusammenhängende Datenpuffer verarbeiten.

+0

Dies kann definitiv auf der Python-Seite getan werden (ctypes gibt Ihnen alle Maschinen, die benötigt werden, um Zeiger zu dereferenzieren), aber Sie haben Recht, dass numpy nur mit zusammenhängenden Datenpuffern funktioniert. Natürlich ist es möglich (aber unwahrscheinlich), dass die Daten zusammenhängend sind. – Eric

+0

Ich verstehe Ctypes können Sie Zeiger manipulieren, aber ich glaube nicht, dass Sie das Äquivalent von numpy '' PyArray_SimpleNewFromData'' von der Python-Seite aufrufen können (obwohl ich würde Sei froh, dass du dich als falsch erwiesen hast!) – jakevdp

+0

Ich denke [diese Frage] (https: // stackoverflow.com/questions/4355524/getting-data-from-ctypes-array-in-numpy) löst den 1D-Fall, und da die Daten sowieso disjunkt sind, ist das das Beste, was Sie tun können. – Eric

0

Mit NumPy und numpy.i ist diese

Schnittstelle Kopf

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

Implementierung

#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 Schnittstelle Kopf

%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" 

Das t ganz einfach ypemap ARGOUTVIEWM_ARRAY2 erstellt ein verwaltetes NumPy-Array und free wird automatisch aufgerufen, wenn das NumPy-Objekt in Python zerstört wird.

Wenn Sie den Wrapper selbst mit der Python-C-API erstellen möchten, können Sie den generierten Code, hergestellt von SWIG Blick in Verwendung numpy.i

Verwandte Themen