Cleanup PyObjects

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
DonnerCobra
User
Beiträge: 53
Registriert: Mittwoch 9. April 2008, 19:35

Montag 16. Juni 2008, 09:23

Hallo,

ich habe ein Problem mit der Anbindung von python in C++ (Nein, bitte keine Links zu Boost oder Swig, das ist aus verschiedenen Gründen nicht möglich). :)


Und zwar habe ich folgendes Problem.

Code: Alles auswählen

Py_Initialize()   

[...]// registriert 5000 Konstanten und einige Objekte sowie Methoden

PyRun_SimpleString("Input1 = 3 \n    Output1 = Input1");

[...] //Code zum herausfischen von Output1 (in dem Beispiel ist Output1 = 3)

PyRun_SimpleString("Output1 = Input1");

[...]/* Code zum herausfischen von Output1. Eigentlich sollte jetzt ein
   Fehler erscheinen das Input1 nicht definiert ist, aber er kennt es noch aus 
   dem ersten Durchlauf. Kann man dazwischen was setzen ohne das meine 
   Konstanten und registrierten Objekte flöten gehen? */

Py_Finalize();

Gibt es eine Möglichkeit ZWISCHEN den beiden PyRun_SimpleString einen Befehl zu setzen indem ich alle im Code erzeugten Objekte lösche? Ich hatte zuerst daran geacht zwischen den beiden Befehlen wieder

Py_Finalize();
Py_Initialize();

zu setzen, jedoch bin ich auf die 5000 Konstanten angewiesen und die registrierung aller Konstanten dauert einfach zu lange und aus Performancegründen sollten die beien PyRun_SimpleString Befehle getrennt werden, aber schnell hintereinander ablaufen.

Kann mir jemand helfen? Danke!

bearbeitet von mitsuhiko: Kommentare umgebrochen
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Montag 16. Juni 2008, 09:46

Vielleicht verstehen Dich andere, aber ich muß vorher noch nachfragen: Von welchem Typ sind diese Objekte, die Du löschen möchtest? PyObject-Zeiger? Und wie sehen Deine "Konstanten" aus? Sind das auch Python-Objekte? Oder haben die einen anderen Typ? Und: Kannst Du einen C++-Iterator über die angelegten Objekte bekommen oder geht es in dem Code nicht?

Gruß,
Christian
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

Montag 16. Juni 2008, 09:58

PyRun_Simple packt deine Objekte auf das main Modul. Ich glaub nicht, dass du das willst. Mach lieber PyRun_String("code", Py_file_input, f_globals, f_locals) wo du f_locals auf ein frisches Dict zeigen lässt.

//EDIT: Hier ein Beispiel zu PyRun_String: http://www.python-forum.de/post-98458.html#98458
TUFKAB – the user formerly known as blackbird
DonnerCobra
User
Beiträge: 53
Registriert: Mittwoch 9. April 2008, 19:35

Montag 16. Juni 2008, 10:44

@CM:

Ja, es sind alles Zeiger.

@mutsuhiko:
ich probiere das mal aus, danke :)
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Montag 16. Juni 2008, 11:33

Abgesehen vom wertvollen Tipp von mitsuhiko, reicht da nicht ein Py_CLEAR auf die zu löschenden Objekte?
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

Montag 16. Juni 2008, 11:53

CM hat geschrieben:Abgesehen vom wertvollen Tipp von mitsuhiko, reicht da nicht ein Py_CLEAR auf die zu löschenden Objekte?
Das Modul hat noch eine Referenz auf das Objekt. Da Py_CLEAR drüberlaufen zu lassen dürfte undefiniertes Verhalten haben. Soweit ich weiß ist Py_CLEAR nur für Funktionen in tp_clear slots gedacht.
TUFKAB – the user formerly known as blackbird
DonnerCobra
User
Beiträge: 53
Registriert: Mittwoch 9. April 2008, 19:35

Montag 16. Juni 2008, 15:21

hi, es scheint zu funktionieren. es wird sich auf dauer zeigen, ob es wirklich geklappt hat. Ich probiere einfach ein paar Skripte aus :)

Danke nochmal :)
DonnerCobra
User
Beiträge: 53
Registriert: Mittwoch 9. April 2008, 19:35

Montag 16. Juni 2008, 18:31

Hi!

Ich war zu voreilig. Mein Programm sieht bis jetzt so aus.

Folgende Funktion wird aufgerufen wenn das Programm gestartet wird:

Code: Alles auswählen


Py_Initialize();
m = Py_InitModule("test", mathMethods);   //fügt das Module test hinzu
	if (m == NULL) return false;
Dann wird aus einer Klasse jeweils ein Objekt erzeugt.

Code: Alles auswählen


init_calculation()...
{
    modules = PyImport_AddModule("__main__");
			dictionaries = PyModule_GetDict(modules);
}


calculation()...
{
       PyDict_SetItem(dictionaries, PyString_FromString("test", PyInt_FromLong(300));


        rv = PyRun_String("<hier ist der python code>", Py_file_input, dictionaries, dictionaries); 

        r1 = PyDict_GetItemString(dictionaries, "test" );
       [...]
}

free_calulcation()...
{
      Py_DECREF(rv);
      Py_DECREF(dictionaries);
}

Übrigens, in Zeile 12 schmiert er ab... :-( Bei PyDict_SetItem...



Mache ich etwas falsch? Danke für eure Hilfe
Zuletzt geändert von DonnerCobra am Montag 16. Juni 2008, 19:07, insgesamt 1-mal geändert.
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

Montag 16. Juni 2008, 18:46

mitsuhiko hat geschrieben:
CM hat geschrieben:Abgesehen vom wertvollen Tipp von mitsuhiko, reicht da nicht ein Py_CLEAR auf die zu löschenden Objekte?
Das Modul hat noch eine Referenz auf das Objekt. Da Py_CLEAR drüberlaufen zu lassen dürfte undefiniertes Verhalten haben. Soweit ich weiß ist Py_CLEAR nur für Funktionen in tp_clear slots gedacht.
Nö. Py_CLEAR ist nur ein sicherer Weg, ``Py_DECREF(x); x = NULL`` zu sagen.
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

Montag 16. Juni 2008, 19:56

birkenfeld hat geschrieben:Nö. Py_CLEAR ist nur ein sicherer Weg, ``Py_DECREF(x); x = NULL`` zu sagen.
Oh. Dann hab ich das mit dem Visit Macro verwechselt.
TUFKAB – the user formerly known as blackbird
DonnerCobra
User
Beiträge: 53
Registriert: Mittwoch 9. April 2008, 19:35

Dienstag 17. Juni 2008, 07:35

Hi!

Hab nochmal eine Sandbox gebaut um mal zu schauen wie das Grundgerüst aussieht.



Code: Alles auswählen

#include <Python/Python.h>
#include <iostream>

PyObject* printer(PyObject* pSelf, PyObject* pArgs)
{
	printf("check OBJECT");
	Py_DECREF(Py_None);
	return Py_None;
}
static PyMethodDef basicMethods[] = {
	{"printer", printer, METH_VARARGS, "Prints out text to the Python Console"},
	{NULL, NULL, 0, NULL}
};



int main (int argc, char * const argv[]) {
	Py_Initialize();
	PyObject *d,*f_globals, *rv;
	
	Py_InitModule("test", basicMethods);
	
	d = PyImport_AddModule("__main__");
	f_globals = PyModule_GetDict(d); 
	rv = PyRun_String("from test import *\n"
				"Input1 = 3", Py_file_input, f_globals,f_globals);
	
	Py_CLEAR(rv);
	Py_CLEAR(f_globals);
	
	
	d = PyImport_AddModule("__main__");
	f_globals = PyModule_GetDict(d); 
	rv = PyRun_String("from test import *\n"
				"Output = Input1\nprint(Output)", Py_file_input, f_globals,f_globals);
	
	Py_Finalize();
    return 0;
}
Dabei sollen die beiden PyRun_Strings seperat voneinander ablaufen, jedoch sollen beide test importieren können.
Jedoch bekomm ich diese Fehlermeldung nicht weg.



Assertion failed: (gc->gc.gc_refs != 0), function visit_decref, file Modules/gcmodule.c, line 276.

Danke für die Hilfe :)
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Dienstag 17. Juni 2008, 12:00

Hoi,

Mach' doch mal an verschiedenen Stellen im Code

Code: Alles auswählen

printf("%f\n", obj->ob_refcnt);
für die drei Pythonobjekte. Führt Dich das auf die Spur? Mir hat man den Tipp letztens gegeben und ich fand ihn ganz hilfreich.

HTH
Christian

edit:
PS Was passiert eigentlich mit 'rv' vor der Rückgabe? Soll das so sein?

PPS
birkenfeld hat geschrieben:Py_CLEAR ist nur ein sicherer Weg, ``Py_DECREF(x); x = NULL`` zu sagen
Eigentlich

Code: Alles auswählen

Py_XDECREF(x); x = NULL
edit2: aus ->-> im Code -> gemacht :oops:
DonnerCobra
User
Beiträge: 53
Registriert: Mittwoch 9. April 2008, 19:35

Freitag 20. Juni 2008, 13:28

Hi!

Ich bekomme es zum verrecken nicht hin, entweder sind die erzeugten Methoden nicht mehr abrufbar weil er sie nicht kennt, oder das alte Problem besteht weiterhin dass er Variablen in den zweiten Run mitnimmt :-(
Antworten