passing string byref in a method

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.
Antworten
Muchtar
User
Beiträge: 10
Registriert: Montag 14. Oktober 2013, 13:32

hallo leute, das ist mein erstes Thema. bin neu bei python. Meine frage ist wie betreff zeigt, wie kann ich ein string-param byref weitergebe? ich habe create_string_buffer() propiert aber wenn ich neuen inhalt anlege, spring "ValueError. too long string". wrapper? bitte helft mir mit eine simplen Lösung.

danke!
muchtar
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Muchtar hat geschrieben:Meine frage ist wie betreff zeigt, wie kann ich ein string-param byref weitergebe?
Strings sind unveränderbar. Zudem existiert ein Konzept wie ByValue oder ByRef in der Form in Python nicht.

Du kannst allerdings eine Liste übergeben und deren Inhalte ändern.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo und willkommen im Forum!

Ich nehme mal an, dass du mit ctypes arbeitest. Da solltest du schon erwähnen. Dann ist natürlich interessant, welche Fehlermeldung du genau bekommst. Inklusive des gesamten Tracebacks. Und natürlich solltest du auch ein minimales *lauffähiges* Beispiel zeigen, welches den Fehler auch reproduziert. Beim Erstellen lösen sich die meisten Probleme dann schon von alleine.
Das Leben ist wie ein Tennisball.
Muchtar
User
Beiträge: 10
Registriert: Montag 14. Oktober 2013, 13:32

danke euch beide. ich glaube ich kriege das hin mit liste. Ich kenn prolog ganz gut und es ähnlet sich mit python auch einiger maßen. Und ja das ist mein aller erste aufgabe n python. nach erstem googlen landete ich an ctypes stimmt.
Obwohl ich es mit liste machen möchte, hier ist den fall

Code: Alles auswählen

                        xmlAsStrBuffer = create_string_buffer("") 
			result = self.myserializeInternal(model,fileName,xmlAsStrBuffer)

Code: Alles auswählen

def myserializeInternal(model,fileName,xmlAsStrBuffer):
                        #...
                        file = open(fileName)
			resize(xmlAsStrBuffer,file.__sizeof__()*5)
			xmlAsStrBuffer.value = file.read()
			#file.close()
			xmlAsStrBuffer.value = etree.tostring(root,encoding="UTF-8") 
                        #...
exception war
Traceback (most recent call last):
File "C:\ws\.......Serializer.py", line 52, in myserializeInternal
xmlAsStrBuffer.value = file.read()
ValueError: string too long


Muchtar
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

``file.__sizeof__`` liefert nicht die Größe der Datei, sondern die größe des Dateiobjekts. Am einfachsten bekommst du es gelöst, wenn du deinen Code etwas umstellst:

Code: Alles auswählen

with open(filename) as fp:
    string_buffer = ctypes.create_string_buffer(fp.read())
Verändere nicht immer ein Objekt, erstelle einfach immer neue. Außerdem solltest du mal einen Blick in PEP 8 werfen, dann kannst du deinen Code näher am Standard halten.
Das Leben ist wie ein Tennisball.
BlackJack

@Muchtar: Was willst Du denn *eigentlich* machen? `ctypes` ist dazu da um mit in C geschriebenen, oder zumindest von C aus ansprechbaren Bibliotheken zu kommunizieren. Nicht um damit in reinem Python-Quelltext Zeichenketten/Byteketten in „Arrays” zu speichern.

Die Fehlermeldung sollte übrigens selbsterklärend sein: Die Datei enthält mehr Bytes als in den `ctypes`-Datentyp passen. Das sieht alles sehr komisch aus was Du da machst.
Muchtar
User
Beiträge: 10
Registriert: Montag 14. Oktober 2013, 13:32

Hallo BlackJack hallo EyDu,

Danke. Ich habe es mit Listen gelöst. Es ging darum dass ich ein String-param byref übergeben möchte. Was ich mache ist es, xml-serializer-funktion die None oder "failed" als Ergebniss returnt mit einem byref-param welche den Inhalt des serialisierten XML als string hält um dann außerhalb der Funktion den XML anhand ein schema zu validieren. Verzeiht mir bitte mein Deusch :D

Grüße,
Muchtar
BlackJack

@Muchtar: Das ist eine furchtbare API. Python ist kein C wo man einen Zeiger für das Ergebnis übergibt und den Rückgabewert für einen Fehlercode verwendet. Du solltest da nichts ”by ref” übergeben sondern einfach das XML zurückgeben. Und falls es einen Fehler gibt eine Ausnahme auslösen.
Muchtar
User
Beiträge: 10
Registriert: Montag 14. Oktober 2013, 13:32

Hallo BlackJack, ich bin 100% deiner Meinung. Was Du gesagt hast is mein style seitdem ich vb.net verlassen habe. Ich versuche meinen Projektleiter zu überzeugen :).

Gute Nacht,
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@Muchtar: ich habe die Trennung zwischen externen Library und Python bei Dir noch nicht ganz verstanden. Vielleicht, weil sie nicht existiert. Idealer Weise sollten nur direkt vor dem Aufruf von über ctypes eingebundene Funktionen die Parameter in ctypes-Variablen kopiert werden, falls nötig. Strings werden auch direkt unterstützt und passend konvertiert. Das findet in einer Wrapper-Funktion statt, die nur diesen Aufruf enthält und (außer Fehlerbehandlung) sonst keine höheren Aufgaben hat. Für Python-Funktionen gilt: Input kommt über Parameter hinein, Output über die Rückgabewerte zurück, Fehler erzeugen Exceptions. Jede Trickserei mit Listen führt zu unlesbarem und unwartbarem Code.
Antworten