Python mit C erweitern: Übergeben Sie eine Liste an PyArg_ParseTuple

8

Ich habe versucht, Python mit C zu erweitern, und zwar bisher basierend auf der Dokumentation < Ich hatte einen vernünftigen Erfolg beim Schreiben kleiner C-Funktionen und erweiterte es mit Python.

Ich bin jedoch jetzt auf ein ziemlich einfaches Problem gestoßen, zu dem ich keine Lösung finden kann. Also, was ich tun möchte, ist ein double list an meine C-Funktion übergeben. Um beispielsweise int zu übergeben, mache ich Folgendes:

%Vor%

Dies übergibt die int n ohne Probleme an meine C-Funktion namens squared .

Aber wie wird ein list an die C-Funktion übergeben? Ich habe versucht, es zu googeln und die Dokumente zu lesen, und bis jetzt habe ich nichts Nützliches dazu gefunden.

Würde mich wirklich freuen, wenn mir jemand in die richtige Richtung zeigen könnte.

Danke.

    
JohnJ 17.03.2014, 15:22
quelle

2 Antworten

9

PyArg_ParseTuple kann nur einfache C-Typen, komplexe Zahlen, char * , PyStringObject * , PyUnicodeObject * und PyObject * . Die einzige Möglichkeit, mit einem PyListObject zu arbeiten, besteht darin, eine Variante von "O" zu verwenden und das Objekt als PyObject * zu extrahieren. Sie können dann mithilfe der Listenobjekt-API überprüfen, ob das Objekt tatsächlich eine Liste ist ( PyList_Check ). Dann können Sie PyList_Size und PyList_GetItem verwenden, um über die Liste zu iterieren. Bitte beachten Sie, dass Sie beim Iterieren PyObject * erhalten und die Fließkomma-API um auf die tatsächlichen Werte zuzugreifen (indem Sie PyFloat_Check und PyFloat_AsDouble ausführen.) Als Alternative zur List-API können Sie flexibler sein und iterator-Protokoll (in diesem Fall sollten Sie einfach PyIter_Check verwenden). Dadurch können Sie über alles, was das Iteratorprotokoll unterstützt, wie Listen, Tupel, Sets usw., iterieren.

Wenn Sie wirklich möchten, dass Ihre Funktion double n[] akzeptiert und Sie all diese manuelle Konvertierung vermeiden möchten, sollten Sie etwas wie boost :: python . Die Lernkurve und APIs sind komplexer, aber boost :: python wird automatisch alle Konvertierungen für Sie übernehmen.

Hier ist ein Beispiel für das Schleifen mit dem Iterator-Protokoll (das ist nicht getestet und Sie müssten den Fehlerbehandlungscode eingeben):

%Vor%     
Nathan Binkert 18.03.2014 17:42
quelle
4

Mit der Funktion PyArg_ParseTuple können Sie direkt in einen Python-Objekt-Subtyp mit der Formatzeichenfolge umwandeln "O!" (notice-das ist anders als nur einfach "O" ). Wenn das Argument nicht mit dem angegebenen PyObject-Typ übereinstimmt, wird ein TypeError ausgelöst. Zum Beispiel:

%Vor%

Beachten Sie, dass das Iterieren über die Liste mit PyList_GetItem eine geliehene Referenz auf jedes Element zurückgibt, so dass Sie Py_DECREF(item) nicht benötigen, um die Referenzzähler . Auf der anderen Seite mit dem nützlichen Iterator-Protokoll (siehe Antwort von @NathanBinkert), jedes zurückgegebene Element ist eine neue Referenz - Sie müssen also daran denken, es zu verwerfen getan mit Py_DECREF(item) .

    
Matt P 17.03.2017 22:57
quelle