Eine existierende Qt C++ App mit Python erweitern können
Eine existierende Qt C++ App mit Python erweitern können
Hallo ich war mir nicht sicher ob besser hier oder in "Einfach Qt" Unterforum. Ich habe praktisch kaum Ahnung von qt bis jetzt.
Folgende größere Sache schwant mir vor (es geht jetzt für mich darum, in Erfahrung zu bringen, wie weit das möglich ist) :
Ihr kennt doch sicher die meisten den Krusader.
Es geht mir um die Möglichkeit (ich bin ohnehin nicht Entwickler bei diesem Projekt).
In dem ganzen Dschungel sip, pythonqt, kross, swig, boost, direkt embedden und extenden kenne ich mich bald nicht mehr aus.
Meine Frage ist, wie kann man mit möglichst wenig Aufwand den maximalen Zugriff auf Krusader von Python aus haben. Ohne jedoch beim Source code
viel ändern zu müssen
Also als erstes bräuchte ich ein Plugin Verwaltung (Managment) (also wie gesagt verwalten, laden, starten, entfernen, deaktivieren)
Wenn ich das richtig sehe, brauche ich sowohl embedding (von C++ heraus auf Pyhton zuzugreifen) als auch extending (also auf die Objekte sollen (am besten alles, nicht wie beim kross nur die slot funktionien), member Variablen (und Objektpointer), Funktionen; wie auch interene queue Variablen zB). Das heisst, ich möchte
mich nicht auf ein paar exportierte Methoden verlassen können, sondern auch die Variablen im Objekt ändern können.
zB. in der Form: kapp.getmainview().getactivepanel()->feedListbox(<myvars>). Da wäre am einfachsten (pseudocode):
import kapp (oder import krusader)
kapp...
Es sollte auch möglich sein, Menü Einträge anhängen zu könenn und Keyboard Shortcuts zuzuweisen.
Ist das richtig so? Ist das schaffbar? Wäre das viel Aufwand?
Vielen Dank schon mal im voraus!
Folgende größere Sache schwant mir vor (es geht jetzt für mich darum, in Erfahrung zu bringen, wie weit das möglich ist) :
Ihr kennt doch sicher die meisten den Krusader.
Es geht mir um die Möglichkeit (ich bin ohnehin nicht Entwickler bei diesem Projekt).
In dem ganzen Dschungel sip, pythonqt, kross, swig, boost, direkt embedden und extenden kenne ich mich bald nicht mehr aus.
Meine Frage ist, wie kann man mit möglichst wenig Aufwand den maximalen Zugriff auf Krusader von Python aus haben. Ohne jedoch beim Source code
viel ändern zu müssen
Also als erstes bräuchte ich ein Plugin Verwaltung (Managment) (also wie gesagt verwalten, laden, starten, entfernen, deaktivieren)
Wenn ich das richtig sehe, brauche ich sowohl embedding (von C++ heraus auf Pyhton zuzugreifen) als auch extending (also auf die Objekte sollen (am besten alles, nicht wie beim kross nur die slot funktionien), member Variablen (und Objektpointer), Funktionen; wie auch interene queue Variablen zB). Das heisst, ich möchte
mich nicht auf ein paar exportierte Methoden verlassen können, sondern auch die Variablen im Objekt ändern können.
zB. in der Form: kapp.getmainview().getactivepanel()->feedListbox(<myvars>). Da wäre am einfachsten (pseudocode):
import kapp (oder import krusader)
kapp...
Es sollte auch möglich sein, Menü Einträge anhängen zu könenn und Keyboard Shortcuts zuzuweisen.
Ist das richtig so? Ist das schaffbar? Wäre das viel Aufwand?
Vielen Dank schon mal im voraus!
Schaffbar iss sicher alles.
Nur der Aufwand iss IMHO heftig .
Krusader kenn ich gar ned, also keine ahnung von was du sprichst ^^
Aber:
python code von ner c++ app ausfuehren:
Das eigentliche iss gar ned so schwer. py dateien in den interpreter laden + einsprungsfunktion aufrufen = 10 zeiler, wenn keinerlei daten uebergeben werden.
Müssen daten uebergeben werden, und von python heraus manipuliert werden -> aua, du breuchst python wrapper, die deine daten in python verstaendliche Daten aendern. Kann je nach Typ der daten unendlicher aufwand bedeuten. Pods gehen sicher recht schnell, aber komplexe c++ datenstrukturen abstracte klassen Hirarchien usw wird sicher nen schoenes gefrimmel
Ne App von python aus fernsteuern:
Du brauchst nen IPC mechanismus !
unter linux wuerde sich gleich DBus anbieten, das kann python nativ auch. Brauchst nur noch bissi den dbus in python wrappen, so das intuitiv verwendbare objecte rausbekommst. aber auch hier, komplexere datenstrukturen werden dir imense probleme machen, bzw musst recht komplex soweiso ueber dbus abbilden.
Knackpunkt iss eher, die App gescheit auf Dbus umzustellen. Das kann auch ne weile dauern.
Ciao ....
Nur der Aufwand iss IMHO heftig .
Krusader kenn ich gar ned, also keine ahnung von was du sprichst ^^
Aber:
python code von ner c++ app ausfuehren:
Das eigentliche iss gar ned so schwer. py dateien in den interpreter laden + einsprungsfunktion aufrufen = 10 zeiler, wenn keinerlei daten uebergeben werden.
Müssen daten uebergeben werden, und von python heraus manipuliert werden -> aua, du breuchst python wrapper, die deine daten in python verstaendliche Daten aendern. Kann je nach Typ der daten unendlicher aufwand bedeuten. Pods gehen sicher recht schnell, aber komplexe c++ datenstrukturen abstracte klassen Hirarchien usw wird sicher nen schoenes gefrimmel
Ne App von python aus fernsteuern:
Du brauchst nen IPC mechanismus !
unter linux wuerde sich gleich DBus anbieten, das kann python nativ auch. Brauchst nur noch bissi den dbus in python wrappen, so das intuitiv verwendbare objecte rausbekommst. aber auch hier, komplexere datenstrukturen werden dir imense probleme machen, bzw musst recht komplex soweiso ueber dbus abbilden.
Knackpunkt iss eher, die App gescheit auf Dbus umzustellen. Das kann auch ne weile dauern.
Ciao ....
Hallo RHBaum,
erstmals danke
Stufe 1 (Python aufrufen von C++) geht schon seit längerem (kein Wunder, das war ja das leichteste). Geht mit kross oder "direkt (der offizielle steinige Weg" mit Python's hauseigene Mitteln.
Ja, aua, da brauche ich einen python wrapper, und da gehts ans Eingemachte.
Nachtrag: ich habe mir einmal das Superkaramba angesehen. Aber das ganze (der Riesenaufwand) ist doch sehr entmutigend. Da könnte mans ja gleich fast völlig neu in pyqt schreiben, mit extending von zeitkritischen Sachen, oder die man sonst nicht in Python hineinbekommen würde.
erstmals danke
Stufe 1 (Python aufrufen von C++) geht schon seit längerem (kein Wunder, das war ja das leichteste). Geht mit kross oder "direkt (der offizielle steinige Weg" mit Python's hauseigene Mitteln.
Ja, aua, da brauche ich einen python wrapper, und da gehts ans Eingemachte.
Nachtrag: ich habe mir einmal das Superkaramba angesehen. Aber das ganze (der Riesenaufwand) ist doch sehr entmutigend. Da könnte mans ja gleich fast völlig neu in pyqt schreiben, mit extending von zeitkritischen Sachen, oder die man sonst nicht in Python hineinbekommen würde.
Diese option besteht immer ....
und ne reine c-dll aufrufen mit pods als parameter aus python raus iss kein Thema.
Komplexere datenstrukturen und hirarchien nach python hineinzuwrappen lohnt sich IMHO nur, wenn man seine funktionalitaet ner breiten masse an anderen Entwicklern zur verfuegung stellen will, also quasi wenn fuer ein atabliertes C++ programm ne python Plugin/erweiterungsschnittstelle oder aehnliches hinzukommen soll. für einmalige verwendung isses sicher overkill.
Auf der anderen seite isses so schwierig nu auch wieder nich. Nur halt eben bissi fleiss. Als erstes c++ Objecte nach c- bringen. Dazu koennte man SWIG verwenden. Und die c-strukturen nach python zu wrappen iss dann nimmer so schlimm. Nur intuitive strukturen dann in python schaffen, das koennt wieder bissi aufwendiger werden.
Ciao ...
und ne reine c-dll aufrufen mit pods als parameter aus python raus iss kein Thema.
Komplexere datenstrukturen und hirarchien nach python hineinzuwrappen lohnt sich IMHO nur, wenn man seine funktionalitaet ner breiten masse an anderen Entwicklern zur verfuegung stellen will, also quasi wenn fuer ein atabliertes C++ programm ne python Plugin/erweiterungsschnittstelle oder aehnliches hinzukommen soll. für einmalige verwendung isses sicher overkill.
Auf der anderen seite isses so schwierig nu auch wieder nich. Nur halt eben bissi fleiss. Als erstes c++ Objecte nach c- bringen. Dazu koennte man SWIG verwenden. Und die c-strukturen nach python zu wrappen iss dann nimmer so schlimm. Nur intuitive strukturen dann in python schaffen, das koennt wieder bissi aufwendiger werden.
Ciao ...
Mit SWIG + CMake ist es absolut easy, seine C++-Klassen in Python verfügbar zu machen. Es geht sogar, dass man in Python eine eigene Klassen von einer in C++ geschriebenen Basisklassen ableitet und virtuelle Funktionsaufrufe erhält.
Was ich aber im Moment versuche (und auf die Schnelle keine Lösung gefunden habe) ist eine Factory-Methode in python, die mir ein PyObject (wieder im C++-Code) liefert (kein Problem), und ich dann dieses in ein C++-Objekt casten kann, welches sich dann wie ein C++-Plugin verhält.
Vielleich weiß ja da einer weiter.
THX!
Was ich aber im Moment versuche (und auf die Schnelle keine Lösung gefunden habe) ist eine Factory-Methode in python, die mir ein PyObject (wieder im C++-Code) liefert (kein Problem), und ich dann dieses in ein C++-Objekt casten kann, welches sich dann wie ein C++-Plugin verhält.
Vielleich weiß ja da einer weiter.
THX!
Also du erstellst in ner python funktion ein Object, was ueber ne C++ dll erstellt wird, und in python nur gewarappt ist ....Factory-Methode in python, die mir ein PyObject (wieder im C++-Code) liefert (kein Problem), und ich dann dieses in ein C++-Objekt casten kann, welches sich dann wie ein C++-Plugin verhält.
dann willst das object ueber ne andere python funktion wieder an ne c++ dll uebergeben und die soll irgendwie das object ned ueber die exportierten funktionen ansprechen sondern "einfach" wieder nach c++ casten und internas verwenden ???
Sicher das beide c++ funktionen im selben prozessraum liegen, so das sie zeiger austauschen koennen ??? Sicher das beide c++ dlls/binaries den selben kompiler verwenden und damit auch binaerkompatibel sind ??? Wenn ja, dann spendier deiner c++ und python Klasse eine "Handle" funktion, die die Adresse der Instanz als rohen zeiger (void * ) nach aussen gibt.
Besser waer aber wenn die 2.te dll nur die auch von python zur verfuegung gestellten und dann wieder nach c++ gewrappten funktionen benutzt. Vielleicht kommst irgendwann doch mal auf den gedanken, die c++ basierte factory durch ne reine python factory zu ersetzen ?
Ich stell mir das so vor (ist schneller mit Code erklärt als mit langen Worten):
Eine Basisklasse für meine Plugins
Jetzt wrapped SWIG das ganze nach python. Dort mache ich ein:
Und nun lädt meine Applikation (also nicht irgendeine DLL) das python-Script, holt sich die create()-Methode (->PyObject*). Ich habe jetzt ein PyObject* und möchte es in ein C++-Object des Typs "cpp::Test*" casten.
Wie geht das?
Es ist sicher, dass die main-app und der SWIG-Wrapper mit dem selben Compiler übersetzt werden.
Eine Basisklasse für meine Plugins
Code: Alles auswählen
namespace cpp { // Dass es klarer ist
class Test
{
virtual void testMe()=0;
public:
virtual ~Test() {}
void test() {
testMe();
}
};
}Code: Alles auswählen
class PyTest (cpp.Test):
def __init__(self):
cpp.Test.__init__(self)
def testMe(self):
print("Python Test")
def create():
return PyTest()Wie geht das?
Code: Alles auswählen
int main()
{
[...]
PyObject* module = PyImport_ImportModule("PyTest"); // PyTest.py
PyObject* factory = PyObject_GetAttrString(module, "create");
PyObject* pytester = PyEval_CallObject(factory, 0);
// Und das geht natürlich nicht...
cpp::Test* t = (cpp::Test*)(pytester); /// wie geht das? Geht das überhaupt?
t->test();
[...]
}Hallo RHBaum und franzf,
danke schon mal. Irgendwie schwirrt mir der Kopf. Ich denke am einfachsten wäre es, so etwas auf minimalistischer Ebene aufzubauen.
Ein ganz kleines Qt C++ Programm (ein, zwei Klassen) zu erstellen.
Dann ruft es einmal ganz normal mit PyInit, pyrunfile, und pyfinalize ein python script auf.
Bis hierher ist es einfach.
Nun wäre es interessant, wie man mit SWIG o. ä. es einmal soweit hinbekomt, dass dann das python script einige Objekte (oder Methoden) sehen kann.
Dann wäre der Bereich Datenaustausch interessant. In wie weit können sich Python und C++ Daten, Objekte, Zeiger teilen. Ideal wäre, wenn Python C++ Objekte ändern kann und andersherum auch.
Mir wäre einmal der "konservative" Weg (also ohne kross) einmal lieber, da man hier das von der Picke auf sehen kann.
Das wäre sicher toll, so ein Template zu haben. Das würde, da bin ich mir sicher, viele andere auch interessieren. Wäre auch eine Wiki Seite wert, IMHO.
Vielleicht ist meine Sichtweise zu naiv...
Nachtrag: Ich sehe gerade, dass es hier eh ein Wiki gibt. Wenn das hier nicht zu offtopic ist, könnte man das ja hier einmal anlegen(?)
danke schon mal. Irgendwie schwirrt mir der Kopf. Ich denke am einfachsten wäre es, so etwas auf minimalistischer Ebene aufzubauen.
Ein ganz kleines Qt C++ Programm (ein, zwei Klassen) zu erstellen.
Dann ruft es einmal ganz normal mit PyInit, pyrunfile, und pyfinalize ein python script auf.
Bis hierher ist es einfach.
Nun wäre es interessant, wie man mit SWIG o. ä. es einmal soweit hinbekomt, dass dann das python script einige Objekte (oder Methoden) sehen kann.
Dann wäre der Bereich Datenaustausch interessant. In wie weit können sich Python und C++ Daten, Objekte, Zeiger teilen. Ideal wäre, wenn Python C++ Objekte ändern kann und andersherum auch.
Mir wäre einmal der "konservative" Weg (also ohne kross) einmal lieber, da man hier das von der Picke auf sehen kann.
Das wäre sicher toll, so ein Template zu haben. Das würde, da bin ich mir sicher, viele andere auch interessieren. Wäre auch eine Wiki Seite wert, IMHO.
Vielleicht ist meine Sichtweise zu naiv...
Nachtrag: Ich sehe gerade, dass es hier eh ein Wiki gibt. Wenn das hier nicht zu offtopic ist, könnte man das ja hier einmal anlegen(?)
@franzf
also wie gesagt, wenn du sicher bist, das beides im selben adressraum residiert, dann
Die handle funktion auch mit nach python exportieren, keine ahnung welcher typ fuer void* gut geeignet waer, und obs da was gibt.
notfalls irgend einen 32bit typ
wieder in c++ geht dann sowas:
Aber ehrlich, ich wuerd sowas meiden wie die Pest.
entweder wuerd ich mit python reine daten ohne klassenfunktionalitaet portieren, oder ich wuerd über python nur die funktionspointer übertragen.
Alles andere waer mir zu unsicher.
und btw: C-casts sind poese ! ^^
Ciao ....
also wie gesagt, wenn du sicher bist, das beides im selben adressraum residiert, dann
Code: Alles auswählen
namespace cpp { // Dass es klarer ist
class Test
{
virtual void testMe()=0;
public:
virtual ~Test() {}
void test() {
testMe();
}
void * getHandle() const
{
return this;
}
};
}
notfalls irgend einen 32bit typ
wieder in c++ geht dann sowas:
Code: Alles auswählen
cpp::Test* t = reinterpret_cast<cpp::Test*>(pytester.gethandle());
entweder wuerd ich mit python reine daten ohne klassenfunktionalitaet portieren, oder ich wuerd über python nur die funktionspointer übertragen.
Alles andere waer mir zu unsicher.
und btw: C-casts sind poese ! ^^
Ciao ....
Da hab ich keine Ahnung... libpython ist ja eine dynamische Lib. Da kenn ich mich zu wenig aus, in welchem Adressraum jetzt die ganzen PyObjects liegen. Ich würde sagen die liegen in dem Speicherbereich, in dem auch mein "main" liegt, da erstell ich die ja auch. Ich wrapp das ganze ja nicht nochmal extra und lad das dynamisch nach.RHBaum hat geschrieben:@franzf
also wie gesagt, wenn du sicher bist, das beides im selben adressraum residiert
Von dem her sollte das klappen.
Code: Alles auswählen
namespace cpp { // Dass es klarer ist
struct Test
{
unsigned long getHandle() const
{
return reinterpret_cast<unsigned long>(this);
}
};
}
Code: Alles auswählen
PyObject* module = PyImport_ImportModule("testapp");
PyObject* factory = PyObject_GetAttrString(module, "create");
PyObject* pytester = PyEval_CallObject(factory, 0);
char method[] = "getHandle";
PyObject* ret = PyObject_CallMethod(pytester, method, 0);
unsigned long address = PyLong_AsUnsignedLong(ret);
Tester* t = reinterpret_cast<Tester*>(address);
t->test();Ich habe mir auch schon überlegt, ob ich nicht ein reines Wrapper-Plugin schreibe, welches ein PyObject* hält (die Python-Instanz meines Plugins) und dann die Kommunikation Aussenwelt<->PyObject übernimmt.Aber ehrlich, ich wuerd sowas meiden wie die Pest.
entweder wuerd ich mit python reine daten ohne klassenfunktionalitaet portieren, oder ich wuerd über python nur die funktionspointer übertragen.
Alles andere waer mir zu unsicher.
Ich frag mich halt, wie andere Frameworks das hinbekommen...
Ich kann Python-Plasmoids auf meinem Desktop anzeigen. Plasma ist aber in C++ geschrieben.
Die Plasmoids können wild mit DataEngines kommunizieren, dabei ist es egal in welcher Sprache die geschrieben sind...
Ich hab schon in den Sourcen geschau, aber bisher noch nicht den entscheidenden Codeabschnitt gefunden
Ja, schon klarund btw: C-casts sind poese ! ^^
Aber mit den C++-casts bin ich nicht weiter gekommen
Danke nochmal, ich werde mein Anliegen nochmal überschlafen