Mit Python ausführende (C++) Programme mit SWIG manipulieren

Python in C/C++ embedden, C-Module, ctypes, Cython, SWIG, SIP etc sind hier richtig.
Antworten
maxmoon
User
Beiträge: 8
Registriert: Freitag 19. Oktober 2012, 17:45

Hallo python-forum-community,

zur Zeit bin ich auf der Suche nach Technologien, um Python in C++ Programmen zu verwenden, bzw. von außen einzuwirken.
Habe daher SWIG probiert und bis jetzt klappt es recht gut z.B. globale Funktionen oder ganze Klassen aus C++ für Python zur Verfügung zu stellen und diese in Python zu nutzen, doch ist das noch nicht wirklich das was ich will.

Ich möchte, wenn ich z.B. eine Konsolenapplikation in C++ geschrieben habe und dort ein Objekt eine Variable (z.B. int i = 42;) besitzt, diese Variable mit Hilfe von Python ändern.

Ist sowas mit SWIG überhaupt möglich?

Für eure Hilfe bin ich sehr dankbar.
lunar

@maxmoon Nein. Du kannst nicht einfach Variablen an wahlfreien Stellen verändern, nicht mal in C++ selbst.
maxmoon
User
Beiträge: 8
Registriert: Freitag 19. Oktober 2012, 17:45

lunar hat geschrieben:@maxmoon Nein. Du kannst nicht einfach Variablen an wahlfreien Stellen verändern, nicht mal in C++ selbst.
Danke für die Antwort, doch ich glaube du hast mich ganz falsch verstanden.

Also in C++ kann ich sehr wohl den Inhalt von Variablen verändern, außer diese sind "const".
Ist ja keine rein funktionale Programmiersprache!

Hier ein kleines und unschönes Programm, um zu zeigen was ich meine:

Code: Alles auswählen

...
int i = 0;
while(true)
{
   i = irgendEinObjekt.getValue();
   std::cout << "i ist jetzt " << i << std::endl;
}
...
"i" kann von mir aus jetzt so deklariert sein, dass es z.B. den Wert einer Variablen einer Klasse bekommt und man auf diese zugreifen kann.
Jetzt möchte ich irgendwie mit Python auf "irgendEinObjekt" zugreifen können, um z.B. den Wert mit "setValue(int i)" setzen zu können, um dann, während das Programm und die whileschleife endlos durchlaufen, den Wert von "i" von außen (also mit Python) zu verändern und die Veränderung während der Laufzeit auch zu sehen.

Meine Frage wäre nun ob SWIG so mächtig ist und dies bewerkstelligen kann?
lunar

@maxmoon Auch in C++ kannst Variablen nicht beliebig verändern. Du kannst beispielsweise nicht von außen lokale Variablen einer Funktion verändern. Dein erster Beitrag aber ließ mich vermuten, dass Du genau das bewerkstelligen möchtest, daher mein Einwand.

Bezogen auf Dein Beispiel, was genau möchtest Du da jetzt aus Python heraus verändern? "i" oder den Inhalt des Objekts, dass an "irgendEinObjekt" gebunden ist?

Zeige doch bitte mal ein minimales, aber vollständiges Stück Quelltext, und erkläre dann anhand dessen, worauf Du genau zugreifen möchtest, denn das ist mir noch immer unklar.
maxmoon
User
Beiträge: 8
Registriert: Freitag 19. Oktober 2012, 17:45

lunar hat geschrieben:@maxmoon Auch in C++ kannst Variablen nicht beliebig verändern. Du kannst beispielsweise nicht von außen lokale Variablen einer Funktion verändern. Dein erster Beitrag aber ließ mich vermuten, dass Du genau das bewerkstelligen möchtest, daher mein Einwand.

Bezogen auf Dein Beispiel, was genau möchtest Du da jetzt aus Python heraus verändern? "i" oder den Inhalt des Objekts, dass an "irgendEinObjekt" gebunden ist?

Zeige doch bitte mal ein minimales, aber vollständiges Stück Quelltext, und erkläre dann anhand dessen, worauf Du genau zugreifen möchtest, denn das ist mir noch immer unklar.
Ja, lokale Variablen von außen zu ändern wäre auch ziemlich sinnlos, denn wenn ich diese von außen ändern möchte, hätte ich diese nicht lokal deklariert :? Aber egal jetzt...

Es ist gänzlich egal ob ich den Inhalt des Objektes oder "i" direkt mit Python verändere. Es geht mir lediglich darum überhaupt etwas zur Laufzeit einer (C++) Applikation mit Python zu verändern. Und ich frage mich nur ob dies mit SWIG realisierbar ist oder ich in diesem Fall auf andere Technologien wie boost.python zugreifen soll?
lunar

@maxmoon Beim allem Respekt, Deine Beiträge erscheinen mir nicht so klar und präzise ausformuliert als dass ich davon ausgehen könnte, Dir wäre selbst vollkommen klar, was Du erreichen möchtest.

Ich verstehe eigentlich immer noch nicht, was Deine Frage ist. Möchtest Du einfach wissen, ob Du mit SWIG irgendwie und irgendwo den Zustand eines C++-Objekts verändern kannst? So pauschal kann man diese Frage natürlich mit ja beantworten, Du brauchst halt einfach nur die entsprechenden Setter mit SWIG zu wrappen. Ist das nicht offensichtlich?
maxmoon
User
Beiträge: 8
Registriert: Freitag 19. Oktober 2012, 17:45

lunar hat geschrieben:@maxmoon Beim allem Respekt, Deine Beiträge erscheinen mir nicht so klar und präzise ausformuliert als dass ich davon ausgehen könnte, Dir wäre selbst vollkommen klar, was Du erreichen möchtest.

Ich verstehe eigentlich immer noch nicht, was Deine Frage ist. Möchtest Du einfach wissen, ob Du mit SWIG irgendwie und irgendwo den Zustand eines C++-Objekts verändern kannst? So pauschal kann man diese Frage natürlich mit ja beantworten, Du brauchst halt einfach nur die entsprechenden Setter mit SWIG zu wrappen. Ist das nicht offensichtlich?
Genau auf so etwas wollte ich heraus und bisher habe ich auch schon herausgefunden, wie ich Klassen mit seinen Methoden wrappe.
So ganz offensichtlich ist es mir jedoch noch nicht und der Haken an der Sache ist, dass wenn ich die Klasse und dessen Methoden wrappe, ich in Python ein eigenes Objekt erzeugen und die Zustände ändern kann, jedoch nicht auf die Zustände des Objekts, das ich in C++ erstellt habe oder habe ich etwas total falsch verstanden?

Ich wäre dir sehr dankbar, wenn du mir erklären könntest, wie du die Zustände eines Objekts, dass in C++ erstellt wurde, mit Python verändert werden kann.

Also bisher hätte ich es so gelöst, dass ich eben die ganze Klasse im Interface für SWIG aufnehme:

Code: Alles auswählen

%module cppklasse
%{
%include "dieKlasse.h"
%}

#include "dieKlasse.h"
In der header datei ist dann halt irgend eine klasse mit setter und getter, z.b.:

Code: Alles auswählen

class CZustandAendern
{
   int i;
public:
   void setI(int i);
   int getI();
};
In der cpp-Datei sind dann die dazugehörigen Implementationen der Methoden. Schreibe ich jetzt nicht dazu, da Setter und Getter für i wohl schon für sich selbst sprechen was die machen.

Meine Bitte wäre jetzt genau zu erklären, wie ich den Zustand eines Objektes, dass ich in C++ erstellt habe, per Python zu ändern.
Also was ich genau machen , bzw. an meinem C++-Programm ändern muss, um das zu bewerkstelligen?

Hier ein Beispiel für das Hauptprogramm:

Code: Alles auswählen

#include <iostream>
#include "dieKlasse.h"

int main()
{
   CZustandAendern testObjekt;
   testObjekt.setI(42);
   
   while(true)
   {
      std::cout << "i ist nun " << testObjekt.getI() << std::endl;
   }
   return 0;
}
...oder bin ich total auf dem Holzweg? :cry:

Danke für die Hilfe
lunar

@maxmoon Du musst Python auch irgendeine Möglichkeit geben, an dieses Objekt zu gelangen. Wie das konkret gehen könnte, hängt von Deinem Programm ab.

Im gezeigten Beispiel müsstest Du überhaupt erst einmal mithilfe der C-API von CPython einen Python-Interpreter in Deinem C++-Programm erzeugen, und in diesem dann Deinen per Swig generierten Wrapper importieren. Dann kannst Du auf verschiedenen Wege, beispielsweise über eine Singleton-Klasse oder indem Du das Objekt direkt in den Python-Interpreter einfügst, das Objekt für Python verfügbar machen.

Ich kann Dir keine konkreteren Hinweise geben, solange Deine Beispiele nicht konkret Deine tatsächliche Situation wiedergeben. Ich nehme nicht an, dass Dein Hauptprogramm nur aus dieser einen Schleife besteht und eine "MeineKlasse" hat.
maxmoon
User
Beiträge: 8
Registriert: Freitag 19. Oktober 2012, 17:45

Doch, das gezeigte Programm zeigt momentan meine tatsächliche Situation (viel komplexer sind meine anderen Programme nicht).
Ich schreibe meine Bachelor-Thesis und muss u.a. verschiedene Technologien vergleichen, darunter auch SWIG.
Und das einzige was ich momentan versuche herauszufinden, ist, wie schon öfters genannt, in eine x-beliebige C++-Applikation per Skript zuzugreifen.

Jedoch habe ich gedacht, dass dies mit SWIG und ohne weiteren Technologien möglich wäre.
Brauche ich denn wirklich noch SWIG, wenn ich CPython verwende?
Kennst du zufällig Tutorials/Bücher/Links zum Thema C-API/CPython und den SWIG-Wrappern oder kannst du mir sogar anhand des simplen Beispiels oben zeigen, wie man es in Python zugänglich macht?
Also wenn SWIG selbst dazu nicht in der Lage ist, dann ist es wohl auch sinnlos damit weiter zu arbeiten und stattdessen CPython, boost.python, etc. zu verwenden.
BlackJack

@maxmoon: Ich habe das Gefühl Dir ist nicht klar was CPython ist: Das ist die „normale” Python-Implementierung von http://www.python.org — CPython deshalb, weil die in C geschrieben ist. Der Begriff wird verwendet, um die Sprache von der konkreten Implementierung zu unterscheiden, wenn das nötig ist.

Auf eine x-beliebige C++-Applikation kann man nicht per Skript zugreifen. Mit keiner anderen Sprache und, wie schon gesagt wurde, auch mit C++ selbst nicht.

Die Frage ob man noch SWIG braucht, wenn man CPython verwendet, ergibt keinen Sinn.

Hast Du denn schon die Dokumentation der jeweiligen Projekte durch? Sowohl in der Python-Dokumentation gibt es ein Tutorial zu erweitern und einbetten von Python, als auch auf der SWIG-Homepage einen Link der „Tutorial” heisst.

In der SWIG-Dokumentation steht übrigens auch warum auf Felder in Strukturen und Klassen nicht zugegriffen werden kann. Und das nicht alle Spracheigenschaften von C++ problemlos auf eine dynamische, interpretierte Sprache abgebildet werden können. Daraus folgt, dass man sich von der Vorstellung jeden beliebigen C++-Code vollautomatisiert statisch „wrappen” zu können verabschieden sollte. Werkzeuge wie SWIG sind nur Hilfen, damit man nicht alles von Hand schreiben muss. Die C-API von Python verstehen und sich Gedanken machen wie man was auf Python abbildet, muss man trotzdem.

Auch beim Einbinden in Dein Programm, und sei es nur Deine kleine Beispielanwendung, scheinst Du zu viel Magie zu erwarten. Irgend wo muss der Programmierer des C++-Programms selbst einen Python-Interpreter integrieren. Das *kann* doch gar nicht automatisiert passieren. Irgendwer muss doch festlegen wo der Interpreter den Programmfluss übernimmt. Und welcher Python-Code dann ausgeführt werden soll. Das kann sich kein Rechner ausdenken, denn die Dinger denken nicht.

Wenn Du SWIG mit anderen Methoden vergleichen sollst, dann solltest Du erst einmal die Methode „manuell” angehen, um dann sehen und darlegen zu können welche Arbeit einem die verschiedenen Hilfsmittel abnehmen. Und Du müsstest vorher mal ein Beispielprogramm definieren, das alle Sprachkonstrukte von C++ verwendet, die Dich interessieren *und* definieren was dann alles von Python aus mit diesem Programm und seinen Komponenten angestellt werden soll. Da kann dann so etwas dabei sein wie Objekt erstellen, Methode aufrufen, und natürlich auch auf ein öffentliches Feld einer Klasse zugreifen. Da kannst Du dann vergleichen ob und wie das mit den verschiedenen Hilfsmitteln möglich ist. Dass das mit SWIG nicht geht ist ein Datenpunkt in so einem Vergleich und kein Grund sich damit erst gar nicht zu beschäftigen. SWIG ist jedenfalls ein relativ verbreitetes Werkzeug um C++ und Python zu verbinden.
maxmoon
User
Beiträge: 8
Registriert: Freitag 19. Oktober 2012, 17:45

Ja, ich merk schon, das führt hier zu nichts.
Das Thema kann man getrost schließen.

Trotzdem danke.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Das du aus der Diskussion so wenig mitnehmen kannst liegt daran, dass du dein Vorhaben nicht konkret beschreibst. Aus deinen Beiträgen wird überhaupt nicht klar, was du eigentlich genau machen möchtest. Hilfreich wäre da die Beschreibung der Problemstellung und nicht bereits die Präsentation aus Sicht einer, von dir so eingeschätzten, Lösungsmöglichkeit.

Was genau möchtest du denn machen?
- Mit Python auf ein anderes Programm zugreifen.
- Python verwenden und Erweiterunge/Bibliotheken nutzen, welche in C++ geschrieben sind
- Ein Programm in C++ schreiben welches Python als Erweiterung benutzt.
Das Leben ist wie ein Tennisball.
BlackJack

@maxmoon: Wenn Du nicht konkreter auf Rückfragen eingehst, dann bringt das tatsächlich nichts. Auf allgemeine Fragen kann man halt auch nur allgemeine Antworten geben.

Wenn Du einen Python-Interpreter in eine C++-Anwendung einbinden willst, dann wirst Du Dich mit der CPython-API auseinander setzen müssen. Da gibt es ein Tutorial, das zeigt wie man so etwas macht. Das wird Dir niemand vorlesen, das musst Du schon selber tun. Insbesondere wäre es unsinnig wenn jemand hier die Beispiele aus diesem Tutorial abschreibt, denn die kannst Du dort genau so gut lesen, ohne dass sie jemand hier abtippen muss.

Und wenn Du etwas mit SWIG wrappen willst, dann erwarten die meisten Benutzer hier, dass Du selbst erst einmal ein wenig Arbeit dort hinein steckst und das SWIG-Tutorial durch arbeitest. Das ist wirklich kurz.

Wenn Du dann *konkrete* Probleme hast, so mit Quelltext und Fehlermeldung oder einer Beschreibung was Du erwartet hast und was stattdessen passiert ist, kannst Du die stellen und auch *konkrete* Antworten erhalten.

Beides, einbetten und wrappen sind in den Grundlagen nun wirklich einfach genug, dass Du Dir das selbst erarbeiten kannst, weil es letztendlich mehr Arbeit ist das für Dich hier zu schreiben, statt dass Du es in den entsprechenden Tutorials und der Dokumentation selber liest.

Ich würde mit dem wrappen anfangen, weil man das einfacher Testen kann, und dann das Ergebnis in die Anwendung einbauen.
maxmoon
User
Beiträge: 8
Registriert: Freitag 19. Oktober 2012, 17:45

EyDu hat geschrieben:Aus deinen Beiträgen wird überhaupt nicht klar, was du eigentlich genau machen möchtest.
Hier ein paar Auszüge aus den vorherigen posts:
"Ich möchte, wenn ich z.B. eine Konsolenapplikation in C++ geschrieben habe und dort ein Objekt eine Variable (z.B. int i = 42;) besitzt, diese Variable mit Hilfe von Python ändern."
"Jetzt möchte ich irgendwie mit Python auf "irgendEinObjekt" zugreifen können, um z.B. den Wert mit "setValue(int i)" setzen zu können, um dann, während das Programm und die whileschleife endlos durchlaufen, den Wert von "i" von außen (also mit Python) zu verändern und die Veränderung während der Laufzeit auch zu sehen."
BlackJack hat geschrieben: Wenn Du einen Python-Interpreter in eine C++-Anwendung einbinden willst, dann wirst Du Dich mit der CPython-API auseinander setzen müssen. Da gibt es ein Tutorial, das zeigt wie man so etwas macht. Das wird Dir niemand vorlesen, das musst Du schon selber tun. Insbesondere wäre es unsinnig wenn jemand hier die Beispiele aus diesem Tutorial abschreibt, denn die kannst Du dort genau so gut lesen, ohne dass sie jemand hier abtippen muss.
Habe nie erwartet, dass mir jemand was vorlesen soll... :(
Die Tutorials haben zwar schön veranschaulicht, wie man Python in C++ nutzt, doch hat das nicht sehr viel zum Erfolg beigetragen. Der Erfolg kam erst später (siehe unten).
BlackJack hat geschrieben: Und wenn Du etwas mit SWIG wrappen willst, dann erwarten die meisten Benutzer hier, dass Du selbst erst einmal ein wenig Arbeit dort hinein steckst und das SWIG-Tutorial durch arbeitest. Das ist wirklich kurz.
Den C++ & Python Teil in der SWIG Doku hatte ich bereits vor diesem Thread gelesen und da ich nicht weiter kam, hatte ich mich hier gemeldet.
BlackJack hat geschrieben: ...
Beides, einbetten und wrappen sind in den Grundlagen nun wirklich einfach genug, dass Du Dir das selbst erarbeiten kannst, weil es letztendlich mehr Arbeit ist das für Dich hier zu schreiben, statt dass Du es in den entsprechenden Tutorials und der Dokumentation selber liest...
Habe das Problem gelöst und so viel Arbeit wäre es eigentlich nicht gewesen es hier zu schreiben. :wink:
Wer jedoch von Anfang an verstanden hatte, was ich wollte und das gleiche Problem hat, der findet auf der folgenden Seite eine geniale Lösung:
http://lahosken.san-francisco.ca.us/fri ... g/doc.html
... vielleicht haben auch nur die Wörter "Extending embedded Python with SWIG" in meinen Beiträgen gefehlt, damit es verständlicher wäre :D

Kurz gesagt ist die Lösung einfach die, dass ein globales Objekt (z.B. das genannte "irgendEinObjekt") erstellt wird und der Methodenaufruf des Objekts in einer globalen Funktion geschieht, die dann von SWIG gewrappt wird. Quasi ein gewrappter Wrapper, wie z.B.:

Code: Alles auswählen

void GlobalerPythonSetter(int i)
{
   irgendEinObjekt.SetValue(i);
}
Von hier an kann man jetzt von Außen mit Python den Zustand der Variablen des C++-Objekts ändern.
lunar

@maxmoon Diese Lösung habe ich Dir bereits genannt. Ich zitiere mich selbst:
Dann kannst Du auf verschiedenen Wege, beispielsweise über eine Singleton-Klasse oder indem Du das Objekt direkt in den Python-Interpreter einfügst, das Objekt für Python verfügbar machen.
Natürlich ist diese Beschreibung abstrakt, doch eben deswegen habe ich auch mehrfach nach einem konkreten Beispiel gefragt, um Dir erklären zu können, wie Du das in Deinem Programm konkret umsetzen kannst. Doch in Deinem Beispiel gab es halt nur „irgendeinObjekt“, und da fällt es mir dann ehrlich gesagt schwer, ein konkretes Problem zu sehen.

Dass Dein Problem letztlich nur darin bestand, den Platz zu finden, an dem Du ein Objekt ablegen kannst, um von anderer Stelle darauf zugreifen zu können – was im Übrigen auch nur mittelbar mit SWIG zu tun hat – war aus Deinen Beiträgen überhaupt nicht ersichtlich.
maxmoon
User
Beiträge: 8
Registriert: Freitag 19. Oktober 2012, 17:45

Lasst uns aufhören zu streiten :D
Die :arrow: Lösung ist ja nun da und wenn wir hier alles zuspammen, kann die Lösung von anderen Usern nicht mehr so gut gefunden werden.

Danke für eure Hilfe.
Antworten