ubuntuusers.de

Für diese Funktion musst du eingeloggt sein.

Aus einem Python-Programm heraus ein c-Programm aufrufen

Status: Ungelöst | Ubuntu-Version: Ubuntu 9.04 (Jaunty Jackalope)
Antworten |

biesta

Anmeldungsdatum:
24. August 2009

Beiträge: 126

Ich möchte aus einem Python-Programm heraus ein eigenes c-Programm aufrufen. Als Anleitung verwende ich dieses: http://docs.python.org/extending/ , aber es klappt noch nicht ganz.

Die Namen hab ich leicht modifiziert; ich stelle mir vor:

>>> import mysys
>>> status = mysys.cmd("ls -l") 

... jetzt sollte eine Dateienliste gezeigt werden (wenns fertig wäre).

Der c-Modul sieht so aus (alles etwas verkürzt):

#include <Python.h>
static PyObject *
mysys_cmd(PyObject *self, PyObject *args)
   {   const char *command;
       int sts;
       if (!PyArg_ParseTuple(args, "s", &command))
          return NULL;
       sts = system(command);
       return Py_BuildValue("i", sts);
   }

Kompilieren tue ich so: gcc -Wall -I /usr/include/python2.6 mysys.c -o mysys_cmd

Leider findet er Grund zum Meckern, nämlich so:

mysys.c:22: Warnung: »mysys_cmd« definiert, aber nicht verwendet
/usr/lib/gcc/x86_64-linux-gnu/4.3.3/../../../../lib/crt1.o: In function `_start':
/build/buildd/glibc-2.9/csu/../sysdeps/x86_64/elf/start.S:109: undefined reference to `main'
/tmp/ccirbVFi.o: In function `mysys_cmd':
mysys.c:(.text+0x23): undefined reference to `PyArg_ParseTuple'
mysys.c:(.text+0x4f): undefined reference to `Py_BuildValue'
collect2: ld gab 1 als Ende-Status zurück

Kann mir jemand auf die Sprünge helfen?

biesta

(Themenstarter)

Anmeldungsdatum:
24. August 2009

Beiträge: 126

Nachtrag: wenn ich beim Kompilieren sage: gcc -Wall -I /usr/include/python2.6 mysys.c ...dann gibt es (fast) die gleichen Fehlermeldungen; (korrigiert) einen Modul 'mysys' den ich importieren könnte - den gibt es auch nicht.

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4679

Wohnort: Berlin

@biesta: Du hast das Modul nicht gegen die Python-Laufzeitbibliothek gelinkt. Danach fehlt aber noch ein bisschen in dem Modul, dass die C-Funktion dann auch als Python-Funktion bekannt macht.

Gibt es einen Grund, warum Du das machen willst, was Du da machst? C-Code würde ich jedenfalls eher mit ctypes aus der Standardbibliothek, oder mittels Cython anbinden. Das macht weniger Arbeit als so ein Modul von Hand zu schreiben.

biesta

(Themenstarter)

Anmeldungsdatum:
24. August 2009

Beiträge: 126

Re: "Gibt es einen Grund, warum Du das machen willst, was Du da machst?" Hauptsächlich wohl den, dass ich (noch) nichts Besseres weiß. Es geht nur darum, aus einem Python-Programm heraus ein bestimmtes C-Programm aufzurufen, jeweils mit ein paar Optionen oder Parametern. Ich versuchs dann mal mit Cython oder ctypes - kannte ich bisher nicht. Bin für jede Entwicklungshilfe dankbar.

PS: das c-Programm existiert bereits, ich kann es aber notfalls modifizieren bzw. anpassen. Es ist ein ziemlich komplexes Programm zur Erfassung von dvb-Daten. Ich hab ganz schnell in das Cython + c-types reingeschaut, das scheint doch eine andere Zielrichtung zu haben. Vielleicht doch besser mit dem ursprünglichen Konzept?

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4679

Wohnort: Berlin

Also irgendwie bin ich noch nicht so ganz im Klaren darüber was Du machen willst. "Ein C-Programm aufrufen" ist nämlich etwas anderes als ein Erweiterungsmodul für Python zu schreiben. Kann es sein, dass Du wirklich nur ein externes Programm aufrufen möchtest? Dann gibt's os.system() als Äquivalent zum system()-Aufruf in C bzw. das subprocess-Modul, das etwas flexibler ist und nicht über eine unnötige Shell gehen muss.

biesta

(Themenstarter)

Anmeldungsdatum:
24. August 2009

Beiträge: 126

Hi, ich versuche mal möglichst klar zu sein.

Das Python-Programm 'fausat' ist im Entstehen. Es ist ein dvb-viewer, den Funktionen nach etwa ein Sat-Receiver mit Festplatte, basierend auf einer dvb-Karte (Technisat Skystar - PCI oder Technotrend S-2400 - USB). Es ist aber nicht für den 'Normalnutzer' gedacht, sondern zum Experimentieren und Forschen für ein Schülerprojekt. Der Python-Teil besorgt die Bedienoberfläche und die konventionellen Funktionen: Dateien manipulieren etc.; alles das sollen die Schüler programmieren.

Der Datenverkehr von der dvb-Karte läuft über etliche c-Programme, teils Standardprogramme wie xine und szap und teils selbstgestrickte wie 'pere'. Alle diese kann ich alternativ in einer Konsole aufrufen, so wie z.B. "$ szap -r zdf", oder so ähnlich auch mit xine oder pere. Insofern ist das fausat ein "interaktiver Stapelbetrieb", wenn man das so sagen will.

Ich habe bereits ein älteres Scriptprogramm in tcl/tk namens teclasat, mit etwa den Funktionen von fausat. Dort erfolgt der Aufruf der externen Programme in der Form "exec szap -r zdf" , also mit dem Schlüsselwort exec und sonst wie in der Konsole. Tatsächlich sind die Aufrufe meistens etwas komplizierter, das ist aber jetzt unwichtig. Jedenfalls ist die Verkoppelung der externen Programme mit dem teclasat nur sehr lose, aber sie funktioniert.

In meiner Naivität hab ich gehofft, so was ginge auch in Python. Weil die Schüler zwar Python gelernt haben, aber kein tcl/tk. Und die c-Programmierung möchte ich ihnen keinesfalls zumuten, diese Programme bekommen sie (hoffentlich...) geliefert.

Mein Ansatz ist also: innerhalb des Python-Programms fausat einen command-string (z.B. szap -r zdf) zu erzeugen und diesen in einer Shell oder sonstwie ausführen zu lassen. Die Ansätze "os.system()" bzw. "subprocess" erscheinen mir vielversprechend, ich werde sie studieren. Wie schon gesagt: ich bin erst am suchen und für jeden Fingerzeig dankbar. 😉

Lunar

Anmeldungsdatum:
17. März 2006

Beiträge: 5792

Nutze subprocess:

1
2
3
4
5
6
7
>>> import subprocess
>>> process = subprocess.Popen(['uname', '-r'], stdout=subprocess.PIPE)
>>> stdout = process.communicate()[0]
>>> stdout
'2.6.30-gentoo-r5\n'
>>> process.returncode
0

biesta

(Themenstarter)

Anmeldungsdatum:
24. August 2009

Beiträge: 126

Nach ein bisschen Experimentieren, und nach einigem Stöbern in der Python-Dokumentation (hier: http://docs.python.org/library/subprocess.html ) klappt schon ein ganz rudimentäres Modell von dem fausat-Programm! Wow, ich bin beeindruckt: (a) wie gut das funktioniert mit dem "subprocess", (b) von eurer guten und schnellen Hilfe. Danke, macht weiter so, ich werde mich bemühen, mich zu revanchieren.

Antworten |