[C API] PyArg_Parse und PyArg_ParseTuple

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
theliquidwave
User
Beiträge: 221
Registriert: Sonntag 1. Juni 2008, 09:08

Hi.
Ich stehe derzeit mal wieder vor einem Problem, dass ich nicht lösen kann.
Unzwar rufe ich eine Funktion auf, die entweder True oder False zurückgeben kann - da kann ich dann PyArg_Parse benutzen. Allerdings möchte ich dem User auch die Möglichkeit geben, nichts zu returnen. Dafür habe ich bei PyArg_Parse einfach die Parameter mit "|b" angegeben - also nichts oder Bool. Allerdings wirft PyArg_Parse dann immer nen System Error, dass die Funktion veraltet sei (oldargs). Mit PyArg_ParseTuple funktioniert dass ganze leider auch nicht so wie ich will, denn da muss ich immer ein "return (True,)" zurückgeben, damit es als Tuple gilt.
Gibt es dafür eine bessere Lösung?

~ Chris
Grüßle.
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Hoi,

den ersten Teil der Frage hatten wir doch schon, oder? (siehe Thread 19353)

Und was Du mit
Chrisber hat geschrieben:Mit PyArg_ParseTuple funktioniert dass ganze leider auch nicht so wie ich will, denn da muss ich immer ein "return (True,)" zurückgeben, damit es als Tuple gilt.
meinst verstehe ich ehrlich gesagt nicht: Mit PyArg_ParseTuple gibtst Du doch nichts zurück, sondern empfängst in der entsprechenden Funktion?

Gruß,
Christian
theliquidwave
User
Beiträge: 221
Registriert: Sonntag 1. Juni 2008, 09:08

Hi.
Naja das Problem ist ja aber, dass PyArg_ParseTuple immer ein Tuple erwartet, d.H. ich muss auch ein Tuple returnen ("return (True,)"), sonst gibts Fehler. Also dachte ich mir, dass ich PyArg_Parse benutze. Allerdings unterstützt PyArg_Parse keine Standardparameter bzw. gibt dann eben diese Meldung mit den oldargs aus.

~ Chris
Grüßle.
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Chrisber hat geschrieben:Naja das Problem ist ja aber, dass PyArg_ParseTuple immer ein Tuple erwartet, d.H. ich muss auch ein Tuple returnen ("return (True,)"), sonst gibts Fehler.
Wieso das denn? PyArg_ParseTuple nimmt Parameter an - und gibt sie nicht zurück. Und bei der Übergabe an Funktionen macht Python das Tuple-Packing/Unpacking automatisch.

Magst Du vielleicht ein wenig Code zeigen, damit ich Dir folgen kann? (Oder sonst jemand schreibt, denn ich stehe echt auf dem Schlauch.)

Gruß,
Christian
theliquidwave
User
Beiträge: 221
Registriert: Sonntag 1. Juni 2008, 09:08

PyArg_ParseTuple soll den Parameter ja auch annehmen :lol:

Ich erklär mal, was ich machen will:
Es geht hier um ein Plugin, welches für das Spiel CS:S konzipiert ist. Es hat auch eine Funktion, bei der man serverseitig die Aufrufe von Funktionen hooken und somit deren Parameter verändern kann. Das ganze möchte ich durch Python leiten, da es ein weiteres Plugin gibt, welches es ermöglicht, dass Pythonscripte auf dem Server unterstützt werden. Nun können die Pythonscripte mein Plugin kontaktieren und bescheid sagen, dass z.B. die Funktion "consolemessage" gehookt werden soll. Der Aufruf durch den Server geht dann durch mein Plugin, welches mit folgendem Code alle registrierten Hooks durchläuft und in den Pythonscripten aufruft:

Code: Alles auswählen

bool bNotBlockTemp = true;
PyArg_Parse(PyEval_CallObject(this->vConCommands[i].pyCallback, Py_BuildValue("(O)", pyList)), "|b", &bNotBlockTemp);
# i stellt den aktuellen Durchlauf als Index dar
Durch den Aufruf wird die Python Funktion aufgerufen. Jetzt soll dem Scripter aber freigestellt sein, ob er True oder False zurückgibt - das funktioniert ja auch. Allerdings gibt es den Fehler, da ich den Rückgabewert als Optional deklariert habe (durch das "|b"). Also entweder kann man nichts zurückgeben (= True, Standard von bNotBlockTemp) oder einen Wert zurückgeben, der dann in bNotBlockTemp gespeichert wird. Wenn das Script "True" oder "False" zurück gibt, gibt es keine Fehler - ohne Rückgabe jedoch schon - und das ist das Problem. Wenn ich allerdings PyArg_ParseTuple verwenden würde, müsste ich immer "return (True,)" zurückgeben, da es sonst wiederrum einen Fehler gibt, weil der Rückgabewert kein Tuple ist.

Ich hoffe du verstehst jetzt, was ich meine :D

~ Chris
Grüßle.
Benutzeravatar
Trundle
User
Beiträge: 591
Registriert: Dienstag 3. Juli 2007, 16:45

Du musst den Rückgabewert von `PyEval_CallObject()` sowieso überprüfen, da er im Fehlerfall NULL sein kann. Also kannst du dann danach einfach etwas wie

Code: Alles auswählen

if (retval != Py_None)
    bNotBlockTemp = PyObject_IsTrue(retval);
machen.

Edit: Wobei man natürlich auch wieder den Rückgabewert von `PyObejct_IsTrue()` prüfen sollte.
"Der Dumme erwartet viel. Der Denkende sagt wenig." ("Herr Keuner" -- Bertolt Brecht)
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Außerdem: Bist Du Dir sicher, daß

Code: Alles auswählen

Py_BuildValue("(O)", pyList)
immer fehlerlos funktioniert? Könnte man sonst ebenso auslagern, wie von Trundle gezeigt.

Generell denke ich, daß das Nesting von Funktionen in C, insb. bei Verwendung der Python-C-API, sehr fehleranfällig ist, weil man leicht was übersieht und dann viel Spaß beim Debugging - ist natürlich nur meine Meinung.

Und ich weiß nicht was "bool" in C ist. Sicher das die API das versteht?

Und zum Schluß "b" als Formatargument spräche nicht ein bool an. Wenn Du bool entsprechend definiert hast, kann das funktionieren - aber ggf. mußt du immer noch eine Konverstion Python-bool zu C-Eigenbau-bool machen, sonst ist der Code (edit: vielleicht) nicht portierbar.

Gruß,
Christian
theliquidwave
User
Beiträge: 221
Registriert: Sonntag 1. Juni 2008, 09:08

Hi.
Danke!
Das funktioniert jetzt.
Ich habe die Checks jetzt mit Py_True und Py_False gemacht - danke :)

~ Chris
Grüßle.
Antworten