So geben Sie ein Array von einer C++-Funktion mit ctypes an Python zurück

Lesezeit: 3 Minuten

Ich verwende ctypes, um eine C++-Funktion in Python zu implementieren. Die C++-Funktion sollte einen Zeiger auf ein Array zurückgeben. Leider habe ich nicht herausgefunden, wie ich in Python auf das Array zugreifen kann. Ich habe numpy.frombuffer ausprobiert, aber das war nicht erfolgreich. Es hat nur ein Array willkürlicher Zahlen zurückgegeben. Offensichtlich habe ich es nicht richtig verwendet. Hier ist ein einfaches Beispiel mit einem Array der Größe 10:

Inhalt der function.cpp:

extern "C" int* function(){
int* information = new int[10];
for(int k=0;k<10;k++){
    information[k] = k;
}
return information;
}

Inhalt von wrapper.py:

import ctypes
import numpy as np

output = ctypes.CDLL('./library.so').function()

ArrayType = ctypes.c_double*10
array_pointer = ctypes.cast(output, ctypes.POINTER(ArrayType))
print np.frombuffer(array_pointer.contents)

Um die C++-Datei zu kompilieren verwende ich:

g++ -c -fPIC function.cpp -o function.o
g++ -shared -Wl,-soname,library.so -o library.so function.o

Haben Sie Vorschläge, was ich tun muss, um auf die Array-Werte in Python zuzugreifen?

  • Natürlich habe ich vergessen, einige spezifische ctypes-Funktionen wie c_double und POINTER zu importieren. Ich habe nur vergessen, sie hier hinzuzufügen.

    – Dolby

    15. Februar 13 um 2:38 Uhr

So geben Sie ein Array von einer C Funktion mit ctypes
Hui Zheng

Ihr Python-Code wird nach einigen geringfügigen Änderungen funktionieren:

import ctypes

f = ctypes.CDLL('./library.so').function
f.restype = ctypes.POINTER(ctypes.c_int * 10)
print [i for i in f().contents] # output: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Grundsätzlich gibt es zwei Änderungen:

  1. numpy-bezogenen Code entfernen und ctypes.cast anrufen, da wir sie nicht brauchen.

  2. Geben Sie den Rückgabetyp an ctypes.POINTER(ctypes.c_int * 10).

    Standardmäßig wird davon ausgegangen, dass Fremdfunktionen den Typ C int zurückgeben, daher müssen wir ihn in den gewünschten Zeigertyp ändern.

Übrigens, Rückgabe von a newed-Array von C-Code zu Python-Code scheint unangemessen. Wer und wann gibt den Speicher frei? Es ist besser, Arrays in Python-Code zu erstellen und sie an C-Code zu übergeben. Auf diese Weise ist klar, dass der Python-Code besitzt die Arrays und übernimmt die Verantwortung für die Schaffung und Rückgewinnung ihrer Räume.

  • Können Sie darauf hinweisen, wie wir ein solches Array in Python erstellen und seinen Zeiger an C übergeben würden?

    – Shahensha

    21. Juli 15 um 5:19 Uhr

  • @Shahensha Was ich für int/float-Arrays mache, ist die Verwendung von numpy-Arrays und der eingebetteten ctypes-Schnittstelle (data_as)

    – Nachteil

    26. April 16 um 14:19 Uhr

  • Ein bisschen Nekromantie hier … Wie würden Sie die Erinnerung löschen, wenn Sie damit fertig sind?

    – XapaJIaMnu

    5. Januar 17 um 18:35 Uhr

So geben Sie ein Array von einer C Funktion mit ctypes
Danika

function.cpp gibt ein int-Array zurück, während wrapper.py versucht, sie als Doubles zu interpretieren. Veränderung ArrayType zu ctypes.c_int * 10 und es sollte funktionieren.


Es ist wahrscheinlich einfacher, es einfach zu verwenden np.ctypeslib anstatt frombuffer du selber. Das sollte in etwa so aussehen

import ctypes
from numpy.ctypeslib import ndpointer

lib = ctypes.CDLL('./library.so')
lib.function.restype = ndpointer(dtype=ctypes.c_int, shape=(10,))

res = lib.function()

  • Ich habe auch c_int importiert und c_double ersetzt, aber Python gibt jetzt ein Array von nur 5 Elementen aus und die Werte sind immer noch falsch. Das ist seltsam.

    – Dolby

    15. Februar 13 um 3:10 Uhr


  • Ausgezeichnet! Vielen Dank! Es funktioniert jetzt. Python gibt mir nur die Warnung “[…] RuntimeWarning: Ungültiger PEP 3118-Formatstring: ‘

    – Dolby

    15. Februar 13 um 3:28 Uhr


  • Ein bisschen Nekromantie hier … Wie würden Sie die Erinnerung löschen, wenn Sie damit fertig sind?

    – XapaJIaMnu

    5. Januar 17 um 18:34 Uhr

  • @XapaJlaMnu Ihre Bibliothek sollte eine entsprechende haben extern C -Funktion aufrufen, um den Speicher freizugeben, der intern C++ verwendet delete wenn es mit belegt wurde new. ctypes verwendet C-Schnittstellen, und da C keine hat delete, ctypes auch nicht.

    – Danika

    5. Januar 17 um 18:39 Uhr

  • Wie in der anderen Antwort vorgeschlagen, ist es nach Möglichkeit normalerweise besser, den Speicher mit numpy zuzuweisen und ihn zum Auffüllen an eine C-Funktion zu übergeben.

    – Danika

    5. Januar 17 um 18:41 Uhr

.

508830cookie-checkSo geben Sie ein Array von einer C++-Funktion mit ctypes an Python zurück

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy