Seite 1 von 1
[C API] PyArg_Parse und PyArg_ParseTuple
Verfasst: Dienstag 7. Juli 2009, 16:01
von theliquidwave
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
Verfasst: Dienstag 7. Juli 2009, 16:35
von CM
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
Verfasst: Dienstag 7. Juli 2009, 16:38
von theliquidwave
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
Verfasst: Dienstag 7. Juli 2009, 16:42
von CM
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
Verfasst: Dienstag 7. Juli 2009, 16:57
von theliquidwave
PyArg_ParseTuple soll den Parameter ja auch annehmen
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
~ Chris
Verfasst: Dienstag 7. Juli 2009, 17:14
von Trundle
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.
Verfasst: Dienstag 7. Juli 2009, 17:42
von CM
Außerdem: Bist Du Dir sicher, daß
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
Verfasst: Dienstag 7. Juli 2009, 17:54
von theliquidwave
Hi.
Danke!
Das funktioniert jetzt.
Ich habe die Checks jetzt mit Py_True und Py_False gemacht - danke
~ Chris