Python/C - [[],[],[],...] an Python übergeben

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Benutzeravatar
windows97
User
Beiträge: 24
Registriert: Freitag 10. März 2006, 13:34

Mittwoch 15. März 2006, 22:36

Hi BlackJack!

Das ist mir schon klar gewesen. Musste nur, wie geschrieben, an den Zeigefinger des Profs denken.

Das mit dem strukturierten Programmcode kommt so langsam glaube ich auch. :roll:
Benutzeravatar
windows97
User
Beiträge: 24
Registriert: Freitag 10. März 2006, 13:34

Freitag 17. März 2006, 14:47

Hallo Heiko!

Bin jetzt dazu gekommen, deinen Vorschlag mal zu Bearbeiten.
Also Problem Nr. 1 ist, dass ich eine Liste als inneres Array brauche und kein Tuple. - Das liesse sich aber wohl noch lösen.
Das Andere Problem liegt jetzt in meinem Verständnis und zwar:
Warum ist bei nem Tuple das Setzen eines items nicht so fehlerkritisch, als bei einer Liste? Das Stehlen der Referenz habe ich doch analog auch bei der Liste.
Desweiteren habe ich jetzt mal mit dem Workaround
#ifdef _DEBUG
#undef _DEBUG
#include "python.h"
#define _DEBUG
#else
#include "python.h"
#endif
das Debuggen mit MsVC ans Laufen bekommen. Hier zeigt sich, das der Referenzzähler des PyData vor dem XDECREF auf 1 steht und danach 14731456 aufweist. Wodurch ist das zu erklären?
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Freitag 17. März 2006, 15:19

Warum ist bei nem Tuple das Setzen eines items nicht so fehlerkritisch, als bei einer Liste? Das Stehlen der Referenz habe ich doch analog auch bei der Liste.
Eben nicht. Wenn Du PyList_Append() machst wird von der Liste eine neue Referenz auf das Objekt gespeichert, bei PyTuple_SET_ITEM() wird eine Referenz gestohlen. Ersteres kann also aus welchem Grund auch immer fehlschlagen (zum Beispiel weil die Liste nicht verlängert werden kann), zweiteres kann nie fehlschlagen, weil der Platz schon vorallokiert ist, deswegen ist es auch ein Makro, während ersteres eine Funktion ist.

Wenn Du umbedingt Listen brauchst kann ich auch Code dafür machen, der sieht aber dann nicht mehr ganz so schön kompakt aus. ;-)
Hier zeigt sich, das der Referenzzähler des PyData vor dem XDECREF auf 1 steht und danach 14731456 aufweist. Wodurch ist das zu erklären?
Wenn der Referenzzähler vorher auf 1 war ist das Objekt nach dem Py_XDECREF unbrauchbar (also freigegeben). Deswegen ist auch der Referenzzähler nicht mehr zu gebrauchen (bzw. der Inhalt unsinnig, und nicht notwendigerweise 0).
--- Heiko.
Benutzeravatar
windows97
User
Beiträge: 24
Registriert: Freitag 10. März 2006, 13:34

Freitag 17. März 2006, 16:11

Dass das bei PyList_Append() auftaucht ist mir vollkommen einleutend gewesen.
Mein Prob liegt darin, das du nen neuen Tuple erzeugen kannst

Code: Alles auswählen

if( !( PyARB_Point = PyTuple_New(0) ) ) goto end_error; 
und dass dieses(?) Tuple dann allokierten Speicher besitzt.
PyList_New(0) aber ja anscheinend nicht...
Wenn Du umbedingt Listen brauchst kann ich auch Code dafür machen, der sieht aber dann nicht mehr ganz so schön kompakt aus. Wink
Untersteh dich! Ich wills selber verstehen. Copy-Paste bringt mir da nicht so wirklich viel. - Aber Danke! :)

Das mit dem Referenzzähler leuchtet ein.
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Freitag 17. März 2006, 16:51

Mein Prob liegt darin, das du nen neuen Tuple erzeugen kannst
Das war nicht ganz richtig was ich da geschrieben hab, das ist mir aber erst jetzt aufgefallen, und es ist erstaunlich dass es anscheinend trotzdem lief, oder?

Auf jeden Fall sollte das sein:

Code: Alles auswählen

if( !( PyARB_Point = PyTuple_New(3) ) ) goto end_error;
Bemerke die 3, die sagt eben dass das Tupel drei Elemente hat, damit ist die Tupelgröße voralloziert, und ändert sich auch nie mehr. Mich wunderts dass es mit 0 (was ich aus Deinem PyList_New(0) übernommen hatte) geht; weil Du im Endeffekt hinter das Array schreibst was die Zeiger auf die Tupelelemente enthält (PyTuple_SET_ITEM ist nämlich nichts anderes als ein einfacher Index-Operator versteckt in einem Makro), und deswegen eigentlich das Programm nicht gehen sollte. Aber, okay, das hat wahrscheinlich was mit der Heap-Überallokation von Python zu tun, so dass Speicher nach dem Array auch schon allokiert ist, aber nicht benutzt war, usw.

Bei Listen stellt man mit dem entsprechenden Parameter ein vieviele Elemente vorallokiert sind (also wie groß das Array am Anfang _mindestens_ sein soll, meißtens ist es größer, weil Python bestimmte Schritte verwendet). Wenn Du dann einen PyList_Append machst und vorher schon mit Größe drei vorallokiert hast wird PyList_Append eigentlich nie fehlschlagen können, weil die Liste ja schon besteht. Dafür müßtest Du Dir aber den Quellcode noch mal genauer angucken. Zumindest würde mir da auch nix einfallen was fehlschlagen könnte.

Auf jeden Fall stiehlt PyList_Append die Referenz eben nicht (soweit ich weiß, wohlgemerkt, aber ich hab gerade im Handbuch nachgeguckt und da steht nix gegenteiliges), während PyTuple_SET_ITEM das sehr wohl macht. Dementsprechend mußt Du wenn Du ersteres benutzt das Element was Du in die Liste einträgst Py_DECREF()-fen, damit nur noch die Referenz aus der Liste draufzeigt, und keine "dangling reference" besteht die vergessen wird wenn Deine Methode sich beendet.
--- Heiko.
Benutzeravatar
windows97
User
Beiträge: 24
Registriert: Freitag 10. März 2006, 13:34

Freitag 17. März 2006, 18:04

Pui, die 3 beruhigt mich jetzt aber extrem!
Hab echt schon vollkommen an mir selbst gezweifelt.

Das ganze Prob ist doch dann ebenso nicht vorhanden, wenn ich PyList_NewList(3) verwende, um eine Liste statt eines Tuples zu erstellen.
Bei PyList_SET_ITEM(x, y, z) verhält es sich ja analog zum Tuple, denn hier wird ja auch die Referenz gestohlen.

Sprich(Schreib): Der Knackpunkt wäre dann das PyList_NewList(3), denn dort wird der Speicher allokiert. Wenn ich dann in der For-Schleife weiter mit PyList_SET_ITEM(x,y,z) arbeite, allokiere ich ja keinen Speicher neu. Ich spiele lediglich Räuber Hotzenplotz mit den Referenzen der item.
Beim PyList_Append der 2-dimensionalen Liste am Ende der FOR-Schleife muss ich dann selbstverständlich wieder Py_DECREF()-fen.
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Freitag 17. März 2006, 18:23

Humm... Ich wollte zuerst ganz was anderes schreiben, aber die Doku ist relativ eindeutig: ja, das sollte so gehen. Okay, auch noch was gelernt. Ich habs bisher immer anders gemacht. ;-)
--- Heiko.
Benutzeravatar
windows97
User
Beiträge: 24
Registriert: Freitag 10. März 2006, 13:34

Freitag 17. März 2006, 18:24

Hey, ich helf doch gern! :lol:

-> Danke!
Antworten