Seite 1 von 1

Objekte in Embedded Interpreter reinladen

Verfasst: Donnerstag 8. Mai 2008, 01:42
von thomas15
Hallo,

ich arbeite an einem Program dass Daten zwischen verschiedenen Scripting- Umgebungen austauschen soll.
Ich habe den Austausch von Python -> Matlab zum laufen gebracht.

Der User kann ein Python Objekt nach Matlab kopieren / referenzieren und dann Matlab anweisungen auf der Kopie/ Referenz laufen lassen, danach das Objekt wieder zurueck nach Python holen. Die Bruecke ist in C++ gehalten.
Jetzt will ich das ganze in die andere Richtung machen Matlab -> Python, aber da muss ich sagen ist Python schon noch Matlab recht hinterher was das angeht.
Mein Ziel ist ganz einfach.
Ich habe ein PyObject und will es in einen embedded Interpreter reinladen, so dass der User mit python Kommandos auf dem Objekt arbeiten kann, von Matlab aus.

Da es im Gegensatz zu Matlab scheinbar keine Funktion in Python gibt die folgerndermassen heissen koennte:

PyObj_Put_Object_Into_Interpreter(PyObject* obj, char* name)

dass der User das Objekt dann in der Konsole mit Python Anweisungen bearbeiten kann

>>> name = name *5 zum Beispiel

habe ich verschiedene andere Ansaetze ausprobiert, mit static Variablen die dann als Modul geladen werden. Geht alles nicht. Ich bezweifle dass ich der Erste mit dem Problem bin. Habe aber bisher noch keinen Link gefunden wo ein aehnliches Problem diskutiert wurde.
Die Boost Libraries sollen als wirklicher Verzweifluns-akt benutzt werden, wobei die nicht generisch genug sind fuer mein Problem, da ich hauptsaechlich mit Numpy Objekten arbeiten will. Ausserdem soll das ganze schlank bleiben.
Zusaetzlich will ich die ganzen Funktionen wie PyImport_ImportModule und PyEval_CallObject nicht benutzen weil das mit aller Warscheinlichkeit den User einschraenken wuerde.


Hat jemand eine Idee? Im Endeffekt ist sollte das wirklich nicht so schwer sein. Wie so vielles... :lol:
Thomas

Verfasst: Donnerstag 8. Mai 2008, 06:28
von mitsuhiko
Hol dir einfach den PyFrame von deinem Interpreter und modifizier das f_locals dict.

Verfasst: Donnerstag 8. Mai 2008, 18:10
von thomas15
Geht das in C++? Wenn ich nach PyFrame Google dann bekomme ich immer nur JYTHON links raus.

Verfasst: Donnerstag 8. Mai 2008, 18:30
von mitsuhiko
thomas15 hat geschrieben:Geht das in C++? Wenn ich nach PyFrame Google dann bekomme ich immer nur JYTHON links raus.
Mein Fehler. Heißt PyFrameObject. Dran kommen kannst du so:

Code: Alles auswählen

PyFrameObject *f = PyThreadState_GET()->frame;
Wenn du schon einen PyThreadState hast, nimm den. Ich bin mir nicht sicher wie du mit dem Interpreter arbeitest.
Einen Namen setzen kannst du etwa so:

Code: Alles auswählen

PyDict_SetItemString(f->f_locals, "my_object", dein_pyobject);

Verfasst: Donnerstag 8. Mai 2008, 18:35
von thomas15
oh cool, ich probiers gleich mal aus...

Verfasst: Donnerstag 8. Mai 2008, 18:58
von thomas15
es kompiliert, schonmal nicht schlecht, aber die rueckgabe von

PyThreadState_GET()->frame == NULL

obwohl ich mir sehr sicher bin dass ein Interpreter geladen wurde und im Speicher existiert.

Code: Alles auswählen

#include <string>
#include "Python.h"
#include "frameobject.h"

int main(int argc,char** args){
	Py_Initialize();

	PyFrameObject *f = PyThreadState_GET()->frame;

       // f==NULL

	PyObject* o = PyString_FromString(std::string("huhu").c_str());

	PyDict_SetItemString(f->f_locals, "a", o);
        //SEGFAULT HIER

	PyRun_SimpleString(std::string("print(a)").c_str());

        return 0;
}
wenn man es im DDD anschaut sieht man das komentierte geschehen. ich muss auch hinzufuegen, ich habe P2.4. Bin in der Umgebung gefangen und kanns deshalb nicht aendern... aber an der Version wirds wohl nicht liegen

Verfasst: Donnerstag 8. Mai 2008, 19:06
von mitsuhiko
Dann gibts wohl noch keinen Interpreter state. Da gibts ein Problem in deiner Überlegung. Ich ging davon aus, dass du versuchst Daten an eine interaktive Python Konsole zu schicken, die in dein Programm eingebettet ist. Anscheinend hast du aber keine solche Konsole und damit auch keinen Frame wo das auftauchen kann.

Also *wo* soll jetzt der Name auftauchen?

Verfasst: Donnerstag 8. Mai 2008, 19:20
von thomas15
also,

ich will einfach aus dem C program Kommandos an die Instanz des Python Interpreters abschicken.

So wie es in dem code ist. das geht ja recht fix mit dem PyRun_SimpleString .
Allerdings soll der Benutzer auch auf seinen Daten arbeiten koennen, die er in den laufenden interpreter reinladen kann.
So stelle ich es mir vor. Habe es genauso von Python mit Matlab gemacht.
Der Python User kann Matlab befehle in der Python Konsole absetzen und auch Objekte hin und her schieben. Das Matlab ist einfach nur im Speicher und nicht fuer den Benutzer sichtbar.
Dachte es ginge auch andersrum:

Der Matlab User setzt Python Befehle aus der Matlab Konsole ab und schickt gegebenenfalls Objekte zwischen beiden hin und her. Eine wirkliche Python Konsole sieht er nicht wirklich. Das Ziel ist hier auch dass die Pythonbefehle auch aus einem Matlab script aus aufgerufen werden koennen, also keine "Interaktivitaet".

Verfasst: Donnerstag 8. Mai 2008, 19:21
von mitsuhiko
Ich glaub du suchst etwa sowas:

Code: Alles auswählen

#include "Python.h"

int main(void)
{
        Py_Initialize();

        PyObject *main_module = PyImport_AddModule("__main__");
        if (!main_module)
                return -1;
        PyObject *f_globals = PyModule_GetDict(main_module);
        PyDict_SetItemString(f_globals, "a", PyString_FromString("Hello World"));

        PyObject *rv = PyRun_String("print a", Py_file_input, f_globals, f_globals);
        if (!rv) {
                PyErr_Print();
                return -1;
        }
        Py_DECREF(rv);
        Py_DECREF(main_module);

        return 0;
}

Verfasst: Donnerstag 8. Mai 2008, 19:24
von thomas15
ich glaub, du hast recht.
es lief...
nach genau dem hab ich gesucht.

was macht
PyImport_AddModule("__main__"); ?

Wird ein neues Modul angelegt? Oder ist nicht das __main__ standard? Bin zudem noch recht Gruen in Python.

Aber der Code von dir scheint genau das zu machen was ich will...

Verfasst: Donnerstag 8. Mai 2008, 19:30
von mitsuhiko
thomas15 hat geschrieben:was macht
PyImport_AddModule("__main__"); ?

Wird ein neues Modul angelegt? Oder ist nicht das __main__ standard? Bin zudem noch recht Gruen in Python.
Da wo du mit PyRun* Code ausführst muss es vorhanden sein wo der Code reingeht. Das ist das __main__ Modul. Von Haus aus ist das nicht da, aber PyRun_Simple erstellt dir eines. Nur das du in dieses Modul halt noch extra Infos reinpacken willst bevor es ausgeführt wird.

Verfasst: Donnerstag 8. Mai 2008, 19:37
von thomas15
ok, cool.
Kann ab hier wieder arbeiten... Super, danke fuer die Hilfe!