Rheinwerk Computing < openbook >

 
Inhaltsverzeichnis
1 Einleitung
2 Die Programmiersprache Python
Teil I Einstieg in Python
3 Erste Schritte im interaktiven Modus
4 Der Weg zum ersten Programm
5 Kontrollstrukturen
6 Dateien
7 Das Laufzeitmodell
8 Funktionen, Methoden und Attribute
9 Informationsquellen zu Python
Teil II Datentypen
10 Das Nichts – NoneType
11 Operatoren
12 Numerische Datentypen
13 Sequenzielle Datentypen
14 Zuordnungen
15 Mengen
16 Collections
17 Datum und Zeit
18 Aufzählungstypen – Enum
Teil III Fortgeschrittene Programmiertechniken
19 Funktionen
20 Modularisierung
21 Objektorientierung
22 Ausnahmebehandlung
23 Iteratoren
24 Kontextobjekte
25 Manipulation von Funktionen und Methoden
Teil IV Die Standardbibliothek
26 Mathematik
27 Kryptografie
28 Reguläre Ausdrücke
29 Schnittstelle zu Betriebssystem und Laufzeitumgebung
30 Kommandozeilenparameter
31 Dateisystem
32 Parallele Programmierung
33 Datenspeicherung
34 Netzwerkkommunikation
35 Debugging und Qualitätssicherung
36 Dokumentation
Teil V Weiterführende Themen
37 Anbindung an andere Programmiersprachen
38 Distribution von Python-Projekten
39 Grafische Benutzeroberflächen
40 Python als serverseitige Programmiersprache im WWW – ein Einstieg in Django
41 Wissenschaftliches Rechnen
42 Insiderwissen
43 Von Python 2 nach Python 3
A Anhang
Stichwortverzeichnis

Download:
- Beispielprogramme, ca. 464 KB

Jetzt Buch bestellen
Ihre Meinung?

Spacer
<< zurück
Python 3 von Johannes Ernesti, Peter Kaiser
Das umfassende Handbuch
Buch: Python 3

Python 3
Pfeil 37 Anbindung an andere Programmiersprachen
Pfeil 37.1 Dynamisch ladbare Bibliotheken – ctypes
Pfeil 37.1.1 Ein einfaches Beispiel
Pfeil 37.1.2 Die eigene Bibliothek
Pfeil 37.1.3 Datentypen
Pfeil 37.1.4 Schnittstellenbeschreibung
Pfeil 37.1.5 Pointer
Pfeil 37.1.6 Strings
Pfeil 37.2 Schreiben von Extensions
Pfeil 37.2.1 Ein einfaches Beispiel
Pfeil 37.2.2 Exceptions
Pfeil 37.2.3 Erzeugen der Extension
Pfeil 37.2.4 Reference Counting
Pfeil 37.3 Python als eingebettete Skriptsprache
Pfeil 37.3.1 Ein einfaches Beispiel
Pfeil 37.3.2 Ein komplexeres Beispiel
Pfeil 37.4 Alternative Interpreter
Pfeil 37.4.1 Interoperabilität mit der Java Runtime Environment – Jython
Pfeil 37.4.2 Interoperabilität mit .NET – IronPython
 
Zum Seitenanfang

37.3    Python als eingebettete Skriptsprache Zur vorigen ÜberschriftZur nächsten Überschrift

In den vorangegangenen Abschnitten haben Sie Möglichkeiten kennengelernt, in C geschriebene Programmteile von einem Python-Programm aus aufzurufen und so beispielsweise laufzeitkritische Teile in ein C-Programm auszulagern.

In diesem Abschnitt wird der entgegengesetzte Weg beschritten: Wir möchten Python-Programme aus einem C/C++-Programm heraus ausführen, Python also als eingebettete Skriptsprache (engl. embedded script language) verwenden. Auf diese Weise können wir bestimmte Teile eines C-Programms in Python schreiben, für die Python aufgrund seiner Flexibilität besser geeignet ist.

 
Zum Seitenanfang

37.3.1    Ein einfaches Beispiel Zur vorigen ÜberschriftZur nächsten Überschrift

Zum Einstieg wird ein C-Programm erstellt, das ein möglichst simples Python-Programm ausführt. Dieses Python-Programm gibt lediglich ein wenig Text und eine Zufallszahl auf dem Bildschirm aus:

#include <Python.h>
const char *programm =
"import random\n"
"print('Guten Tag, die Zahl ist:', random.randint(0, 100))\n"
"print('Das war ... Python')\n";
int main(int argc, char *argv[])
{
Py_Initialize();
PyRun_SimpleString(programm);
Py_Finalize();
}

Zunächst wird die Header-Datei der Python API eingebunden. Sie sehen, dass sowohl zum Erweitern als auch zum Einbetten von Python dieselbe API verwendet wird. Danach wird der String programm angelegt, der den später auszuführenden Python-Code enthält.

In der Hauptfunktion main wird der Python-Interpreter zuerst durch Aufruf von Py_Initialize initialisiert. Danach wird das zuvor im String programm abgelegte Python-Skript durch Aufruf der Funktion PyRun_SimpleString[ 166 ](Anstelle der Funktion PyRun_SimpleString hätten wir auch die Funktion PyRun_SimpleFile aufrufen können, um den Python-Code aus einer Datei zu lesen. ) ausgeführt und der Interpreter schließlich durch die Funktion Py_Finalize wieder beendet.

Wichtig ist, dass dem Compiler das Verzeichnis bekannt ist, in dem die Header-Datei Python.h liegt. Außerdem muss das Programm gegen die Python API gelinkt werden.

Kompilieren unter Windows

Um das Programm unter Windows zu kompilieren, können Sie die Visual Studio Build Tools verwenden, was allerdings mit relativ viel Aufwand bei der Installation verbunden ist.

Alternativ installieren Sie mingw über conda:

conda install mingw

Anschließend müssen Sie einen neuen Anaconda Prompt öffnen, damit der Compiler gefunden wird. Danach können Sie das Programm folgendermaßen übersetzen:

gcc -I%USERPROFILE%\Anaconda3\include -L%USERPROFILE%\Anaconda3  
-lpython36 beispiel.c -o beispiel.exe

Durch den Aufruf wird die Datei beispiel.c in das ausführbare Programm beispiel.exe übersetzt.

Kompilieren unter Linux und macOS

Wenn Sie Anaconda unter Linux oder macOS verwenden, können Sie das Programm folgendermaßen übersetzen, sofern Sie einen entsprechenden Compiler installiert haben:

$ export LIBRARY_PATH=$HOME/anaconda3/lib:$LIBRARY_PATH
$ gcc -I$HOME/anaconda3/include/python3.6m -lpython3.6m beispiel.c -o beispiel

Zum Ausführen müssen Sie noch die Umgebungsvariable PYTHONHOME setzen und dafür sorgen, dass die Python-Bibliothek geladen werden kann:

$ export PYTHONHOME=$HOME/anaconda3/
$ export LD_LIBRARY_PATH=$HOME/anaconda3/lib:$LD_LIBRARY_PATH

Nun können Sie die ausführbare Datei beispiel starten:

$ ./beispiel

Ausführen des Programms

Wenn sowohl das Kompilieren als auch das Linken ohne Probleme erfolgt sind, werden Sie feststellen, dass das Programm tatsächlich funktioniert:

Guten Tag, die Zufallszahl ist: 64
Das war ... Python

Das Python-Skript läuft bislang völlig autonom, und es können keine Werte zwischen ihm und dem C-Programm ausgetauscht werden. Aber gerade die Interaktion mit dem Hauptprogramm macht die Qualität einer eingebetteten Skriptsprache aus.

 
Zum Seitenanfang

37.3.2    Ein komplexeres Beispiel Zur vorigen ÜberschriftZur nächsten Überschrift

Im vorangegangenen Abschnitt haben Sie ein triviales Beispiel für die Einbettung von Python als Skriptsprache kennengelernt. Basierend auf diesen Ergebnissen können wir in diesem Abschnitt ein komplexeres Einsatzbeispiel angehen, in dem Werte über eine Funktionsschnittstelle geschickt bzw. entgegengenommen werden. Außerdem soll das C-Programm dazu in der Lage sein, eigene Funktionen zu definieren, die aus dem Python-Skript heraus aufgerufen werden können. Sie werden feststellen, dass auch dies dem Schreiben von Erweiterungen ähnelt.

Das folgende C-Programm lädt ein Python-Skript, das eine Funktion entscheide implementiert. Diese Funktion soll sich für einen von zwei übergebenen Strings entscheiden. Die Funktion könnte beispielsweise deshalb in ein Python-Skript ausgelagert worden sein, weil der Programmierer es dem Anwender ermöglichen will, die Funktion selbst zu implementieren und das Programm somit an die eigenen Bedürfnisse anzupassen.

Der Quellcode des Beispielprogramms sieht folgendermaßen aus:

#include <Python.h>
int main(int argc, char *argv[])
{
char *ergebnis;
PyObject *modul, *funk, *prm, *ret;
Py_Initialize();
PySys_SetPath(L".");
modul = PyImport_ImportModule("script");
if(modul)
{
funk = PyObject_GetAttrString(modul, "entscheide");
prm = Py_BuildValue("(yy)", "Hallo", "Welt");
ret = PyObject_CallObject(funk, prm);
ergebnis = PyBytes_AsString(ret);
printf("Das Skript hat sich fuer '%s' entschieden\n", ergebnis);
Py_DECREF(prm);
Py_DECREF(ret);
Py_DECREF(funk);
Py_DECREF(modul);
}
else
printf("Fehler: Modul nicht gefunden\n");
Py_Finalize();
}

In der Hauptfunktion main des C-Programms wird zunächst der Python-Interpreter durch Aufruf von Py_Initialize initialisiert. Danach wird durch die Funktion PySys_SetPath das lokale Programmverzeichnis als einziger Ordner festgelegt, aus dem Module importiert werden können. Beachten Sie, dass dieser Funktionsaufruf sowohl dem C- als auch dem Python-Programm verbietet, globale Module wie beispielsweise math einzubinden. Wenn Sie solche Module benötigen, dürfen Sie die import-Pfade nicht, wie es in diesem Beispiel geschehen ist, überschreiben, sondern Sie sollten sich den Pfad mit Py_GetPath holen, ihn um das Verzeichnis . erweitern und mit PySys_SetPath setzen. Beachten Sie, dass das lokale Programmverzeichnis standardmäßig nicht als import-Pfad eingetragen ist.

Durch Aufruf der Funktion PyImport_ImportModule wird ein Modul eingebunden und als PyObject-Pointer zurückgegeben. Wenn die entsprechenden Pfade festgelegt wurden, können sowohl lokale als auch globale Module mit dieser Funktion eingebunden werden. Im Folgenden prüfen wir, ob das Modul erfolgreich geladen wurde. Bei einem Misserfolg gibt die Funktion PyImport_ImportModule wie die meisten anderen Funktionen, die einen PyObject-Pointer zurückgeben, NULL zurück. Beachten Sie, dass es immer ratsam ist, die zurückgegebenen PyObject-Pointer auf NULL zu testen. Im Beispielprogramm wurde dies nur exemplarisch bei modul gemacht.

Nun beziehen wir durch Aufruf der Funktion PyObject_GetAttrString einen Pointer auf die Funktion entscheide des Moduls script. Um die Funktion aufrufen zu können, müssen wir die Funktionsparameter in Form eines Tupels übergeben. Dazu erzeugen wir mittels Py_BuildValue ein neues Tupel, das die beiden bytes-Strings "Hallo" und "Welt" enthält, von denen die Funktion entscheide einen auswählen soll.

Durch Aufruf der Funktion PyObject_CallObject wird die Funktion funk schließlich aufgerufen und ihr Rückgabewert ebenfalls in Form eines Pointers auf PyObject zurückgegeben. Da es sich bei dem Rückgabewert um einen bytes-String handelt, können wir diesen mit PyBytes_AsString zu einem C-String konvertieren und dann mit printf ausgeben.

Die in diesem Beispiel aufgerufene Python-Funktion entscheide sieht folgendermaßen aus und befindet sich in der Programmdatei script.py:

def entscheide(a, b):
return (a if min(a) < min(b) else b)

Die Funktion bekommt zwei Sequenzen a und b übergeben und gibt eine der beiden zurück. Die Entscheidung, welche der beiden Sequenzen zurückgegeben wird, hängt davon ab, welche das in der jeweiligen Ordnungsrelation kleinste Element enthält. Bei zwei Strings bzw. bytes-Strings wird beispielsweise derjenige zurückgegeben, der den alphabetisch kleinsten Buchstaben enthält.

Im nächsten Beispielprogramm soll es dem Python-Skript ermöglicht werden, bestimmte Funktionen des C-Programms aufzurufen. Es soll dem Skript also gewissermaßen eine API zur Verfügung gestellt werden, die es verwenden kann. Diese Idee liegt nicht nur gedanklich nah an den in Abschnitt 37.2, »Schreiben von Extensions«, besprochenen Extensions, sondern wird auch ganz ähnlich umgesetzt. Der Quelltext des Beispielprogramms sieht folgendermaßen aus:

#include <Python.h>
static PyObject *testfunktion(PyObject *self, PyObject *args)
{
int a, b;
if(!PyArg_ParseTuple(args, "ii", &a, &b))
return NULL;
return Py_BuildValue("i", a + b);
}
static PyMethodDef MethodTable[] =
{
{"testfunktion", testfunktion, METH_VARARGS, "Testfunktion"},
{NULL, NULL, 0, NULL}
};
static PyModuleDef APIModule =
{
PyModuleDef_HEAD_INIT,
"api", NULL, -1, MethodTable
};
static PyObject *PyInit_api()
{
return PyModule_Create(&APIModule);
}
int main(int argc, char *argv[])
{
FILE *f;
PyImport_AppendInittab("api", &PyInit_api);
Py_Initialize();
f = _Py_fopen("script.py", "r");
PyRun_SimpleFile(f, "script.py");
fclose(f);
Py_Finalize();
}

Zunächst wird die Funktion testfunktion definiert, die später dem Python-Skript über ein Modul namens api zur Verfügung gestellt werden soll. Im Beispiel berechnet die Funktion schlicht die Summe zweier ganzer Zahlen, die ihr als Parameter übergeben werden. Danach werden die MethodTable und die Moduldefinition erstellt, ganz als würden wir eine Erweiterung schreiben. Ebenfalls analog zu den Erweiterungen wird eine Initialisierungsfunktion für das Modul namens PyInit_api benötigt. Durch Aufruf der Funktion PyImport_AppendInittab wird unser Modul api in die Liste der verfügbaren Module eingetragen.

Schließlich brauchen wir nur noch die Funktion PyRun_SimpleFile aufzurufen, um das Python-Skript script.py zu interpretieren. Der Funktion müssen wir dabei ein geöffnetes Dateiobjekt übergeben.

Das Python-Skript, das von diesem C-Programm aufgerufen wird, kann beispielsweise folgendermaßen aussehen:

import api
print("Zwei plus zwei ist:", api.testfunktion(2, 2))

 


Ihre Meinung

Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.

<< zurück
 Zum Rheinwerk-Shop
Zum Rheinwerk-Shop: Python 3 Python 3
Jetzt Buch bestellen

 Buchempfehlungen
Zum Rheinwerk-Shop: Einstieg in Python
Einstieg in Python


Zum Rheinwerk-Shop: Python. Der Grundkurs
Python. Der Grundkurs


Zum Rheinwerk-Shop: Algorithmen mit Python
Algorithmen mit Python


Zum Rheinwerk-Shop: Objektorientierte Programmierung
Objektorientierte Programmierung


Zum Rheinwerk-Shop: Raspberry Pi. Das umfassende Handbuch
Raspberry Pi. Das umfassende Handbuch


Zum Rheinwerk-Shop: Roboter-Autos mit dem Raspberry Pi
Roboter-Autos mit dem Raspberry Pi


Zum Rheinwerk-Shop: Neuronale Netze programmieren mit Python
Neuronale Netze programmieren mit Python


 Lieferung
Versandkostenfrei bestellen in Deutschland, Österreich und der Schweiz
InfoInfo

 
 


Copyright © Rheinwerk Verlag GmbH 2020
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das Openbook denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt.
Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.

 
[Rheinwerk Computing]

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de

Cookie-Einstellungen ändern