Das Einbetten ist dem Erweitern zunächst einmal sehr ähnlich. Die Schnittstelle, die wir verwenden ist exakt die gleiche und auch die nötigen Schritte ähneln sich, wie folgendes Beispiel zeigt.
Der erste Aufruf, den wir ausführen müssen bevor wir den Python-Interpreter verwenden können und somit Code zur Ausführung bringen, ist der Aufruf von PyInitialize(). Der Aufruf initialisiert alle globalen Datenstrukturen, allokiert den für den Interpreter benötigen Speicher und importiert das Modul __buildins__, das alle eingebauten Python-Funktionen enthält. Nach diesem Funktionsaufruf, steht der Interpreter global (also aus jedem Programmteil) zur Verfügung.
int main(int argc, char *argv[]) { /* Interpreter initialisieren */ Py_Initialize(); if (PyRun_SimpleString("from functools import *\n" "def fakt(n):\n" "\treturn reduce(lambda x,y: x * y, range(1, n+1)) \n" "print(\"Fakultaet von 5 ist: \" + str( fakt(5) ) )") == -1) fprintf(stderr,"Error while interpretation\n"); /* Interpreter beenden */ Py_Finalize(); return 0; }Zunächst wird der Interpreter initialisiert. Im Anschluss kann nun Python-Funktionalität genutzt werden, indem eine einfache Stringkonstante an die Funktion PyRun_SimpleString() übergeben wird. Der Interpreter wird den übergebenden String parsen und interpretieren. Als Funktionsresultat erhalten wir in diesem Fall 0 (kein Fehler bei der Interpretation) und die Ausgabe 120 auf der Standardausgabe. Wie zu erkennen, besteht in diesem Fall keine Möglichkeit Rückgabewerte aus der Funktion zu erhalten oder Parameter direkt zu übergeben.
int main(int argc, char *argv[]) { FILE * fact = fopen("./factorial.py","r"); /* Interpreter initialisieren */ Py_Initialize(); if (PyRun_SimpleFile(fact, "./factorial.py") == -1) fprintf(stderr,"Error while interpretation\n"); /* Interpreter beenden */ Py_Finalize(); fclose(fact); return 0; }Der Unterschied zum ersten Beispiel ist die Verarbeitung eines externen Python-Skripts ./factorial.py. Dieses Beispiel ermöglicht uns z.B. die variable Ausführung von Pythoncode ohne die C-Quelldatei(en) erneut zu übersetzen. (Stichwort Plug-In)
/* ... */ Py_Initialize(); /* Initialisieren des Python-Interpreter */ module = PyImport_Import("xmlwork"); /* Modulimport auslösen */ if (module) { className = PyObject_GetAttrString(module, "Xml"); /* if (className && PyCallable_Check(className)) { /* Konstruktoraufruf Xml("addresses.xml") */ instance = PyObject_CallFunction(className, "(s)", parmImportFile); if (instance) { /* Aufruf dict = instance.load_address_book() */ dict = PyObject_CallMethod(instance, "load_address_book", "") /* ... Verzeichnis verarbeiten ... */ } Py_Finalize(); /* ... */Zunächst muss auch hier der Interpreter initialisiert werden, um überhaupt Code ausführen zu können. Im Anschluss weisen wir den Interpreter an, das Modul xmlwork.py zu importieren. Damit der Interpreter diesen Import durchführen kann, ist es zwingend erforderlich, dass das entsprechende Verzeichnis im Such-Pfad des Interpreters eingetragen ist. Dies kann ggf. durch den Aufruf von PySys_SetPath() erfolgen. Wurde das Modul erfolgreich importiert, wird nun das Objekt (in diesem Fall die Klasse) Xml der Variable className zugewiesen. Ist diese Klasse instanzierbar (PyCallable_Check()), können wir den Konstruktor mit Übergabe der zu importierenden Datei aufrufen (PyObject_CallFunction()). Wir erhalten eine Instanz der Klasse in der Variablen instance und rufen im Folgenden die Methode load_address_book auf. Hier sehen wir nun echte Interaktion, denn der Methodenaufruf liefert uns ein Dictionary zurück, das jetzt mit weiteren Schnittstellenfunktionen auf beliebige Art und Weise verarbeitet werden kann. In der Beispielanwendung wird das Dictionary mit einem Iterator durchlaufen und die Einträge der XML-Datei in einen binären Baum einfügt.
Dieses Beispiel soll verdeutlichen, dass mit wenig Code, nur durch Einbindung des Python-Interpreters schnell eine ordentliche Funktionalität erreicht werden kann. Wie bereits erwähnt bietet sich diese Technik besonders an, wenn Laufzeiteffizienz eine untergeordnete Rolle spielt und Dynamik, Flexibilität und kurze Entwicklungszeiten im Vordergrund stehen.
Eine komplette Version dieses XML-Beispiels finden Sie hier.