VRB News
Virtual Reality Brisbane
  • Home
  • About us
  • IT news
  • Tech
  • World
  • Contact
No Result
View All Result
  • Home
  • About us
  • IT news
  • Tech
  • World
  • Contact
No Result
View All Result
No Result
View All Result
Home IT news

Python erweitern und einbetten

admin by admin
March 18, 2022
in IT news
0
Das mit Abstand am häufigsten verwendete Python (CPython) ist bereits in C implementiert und dürfte vielen Entwicklern bereits geläufig sein. Doch wann ist es nötig, das verwendete Python zu erweitern? Wann ist es eher ratsam, statt in C eine einbettung in C++ vorzunehmen?
0
SHARES
37
VIEWS
Share on FacebookShare on Twitter

 

Fließende Kommunikation zwischen Python und C/C++ Python erweitern und einbetten

15.03.2022Von Rainer Grimm *

Es gibt viele gute Gründe, Python entweder um C/C++ zu erweitern oder in C/C++ einzubetten – grundsätzlich verstehen sich Python und C/C++ nämlich blendend. Am Anfang steht aber die Qual der Wahl: Welche Technik oder welches Framework sollte zum Einsatz kommen? Wann ist es ratsam, Python zu erweitern, wann sollte man es eher in C++ einbetten?

Firma zum Thema

Das mit Abstand am häufigsten verwendete Python (CPython) ist bereits in C implementiert und dürfte vielen Entwicklern bereits geläufig sein. Doch wann ist es nötig, das verwendete Python zu erweitern? Wann ist es eher ratsam, statt in C eine einbettung in C++ vorzunehmen?

Bevor dieser Artikel in die Untiefen der Kommunikation zwischen Python und C/C++ abtaucht, gilt es zuerst, die elementare Frage zu klären: Was bedeutet es, Python um C/C++ zu erweitern beziehungsweise Python in C/C++ einzubetten? Vereinfacht gesagt verhalten sich die beiden Techniken spiegelbildlich zueinander.

Das Erweitern geschieht in den folgenden drei Schritten:

  • Zunächst muss man die Werte von Python nach C/C++ konvertieren.
  • Anschließend kann man die konvertierten Werte verwenden, um die C/C++-Funktionalität auszuführen.
  • Zuletzt lassen sich die Ergebnisse von C/C++ nach Python konvertieren.

Das Einbetten hingegen funktioniert genau umgekehrt: Zuerst werden die Werte von C/C++ nach Python konvertiert, und am Ende steht das Konvertieren der Ergebnisse von C/C++ nach Python. Das Erweitern und Einbetten von Python ist kein Selbstzweck, sondern bietet eine Reihe von Vorteilen. Der Einfachheit halber beschränkt sich folgende Aufzählung auf drei Vorteile.

  • Don’t repeat yourself (DRY).
  • Optimierung des performanzkritischen Teils der Applikation.

Um den Umfang dieses Artikels nicht zu sprengen, werden sich alle Beispiele in diesem Dokument auf Linux beziehen. Die entsprechenden Schritte lassen sich aber auch auf Windows entsprechend durchführen.

Direkte Kommunikation aus Python mit Shared Libraries dank ctypes

Mit dem Modul ctypes lässt sich eine Shared Librarys oder DLL direkt und komfortabel aufrufen. ctypes wird in der Python-Dokumentation als eine Bibliothek für fremde Funktionen beschrieben. Sie stellt mit C kompatible Datentypen zur Verfügung und ermöglicht den Aufruf von Funktionen in den DLLs oder Shared Libraries. Außerdem dient sie dazu, diese Bibliotheken in reinen Python-Code zu verpacken.

Bild 1 zeigt, wie die Shared Library libhelloWorld.so sich direkt laden und die Funktion “helloWorld.helloWorld()” ausführen lässt.

Python direkt erweitern

Für das direkte Erweitern der Python-API und den unmittelbaren Zugriff auf die Python-Laufzeit bietet Python Funktionen, Makros und Variablen an. Die Python-API wird durch die Headerdatei Python.h angeboten und lässt sich nur unter CPython einsetzen. Eigene Erweiterungsmodule in C/C++ für Python zu schreiben ist eine durchaus anspruchsvolle Aufgabe – daher wird das folgende Kapitel in pragmatischer Manier die bekannte Shared Library helloWorld als Erweiterungsmodul implementieren, und folgende Listing stellt das neue Erweiterungsmodul vor.

#define PY_SSIZE_T_CLEAN#include <Python.h>static PyObject* method_helloWorld(PyObject*, PyObject*);static PyMethodDef HelloWorld[] = {    {"helloWorld", method_helloWorld, METH_VARARGS,     "Hello world program"},    NULL, NULL, 0, NULL}};static struct PyModuleDef helloWorldModule = {    PyModuleDef_HEAD_INIT,    "helloWorld",    "Hello World message",    -1,    HelloWorld};static PyObject* method_helloWorld(PyObject* self, PyObject* args) {    printf("Hello Worldn");    Py_INCREF(Py_None);    return Py_None;}PyMODINIT_FUNC PyInit_helloWorld(void) {    return PyModule_Create(&helloWorldModule);}

Zum Verständnis des Listings sind einige Erklärungen hilfreich:

  • Python.h erlaubt den Zugriff auf die Python-API, sie muss die erste Headerdatei sein.
  • static PyMethodDef HelloWorld[ ] definiert die Methodentabelle. Dabei besteht ein Eintrag{“helloWorld”, method_helloWorld, METH_VARARGS, “Hello”} aus dem Namen der Python-Methode helloWorld, dem Namen der korrespondierenden C-Funktion method_helloWorld, der Aufrufkonvention der C-Funktion METH_VARARGS und dem Dokumentationsstring der Python-Methode. Eine Methodentabelle kann mehr als einen Eintrag besitzen, der letzte Eintrag {NULL, NULL, 0, NULL} schließt die Tabelle ab.
  • static struct PyModuleDef helloWorldModule steht für die Definition des Moduls. Das Modul benötigt einen Namen helloWorld sowie den Dokumentationsstring des Moduls Hello World message, und es referenziert die bereits definierte Methodentabelle HelloWorld.
  • PyMODINIT_FUNC sorgt für die Initialisierung des Moduls.

Nun gilt es noch ein Paket zu bauen, das das Modul enthält. Mit dem Python-Modul disutils lässt sich diese Aufgabe für Linux problemlos umsetzen. Für das Erzeugen eines Pakets ist eine setup.py-Datei notwendig. Die Datei setup.py im folgenden Listing stellt eine minimale Konfigurationsdatei für das Paket helloWorld dar.

from distutils.core import setup, Extensiondef main():    setup(name="helloWorld",       ext_modules=[Extension("helloWorld",           ["helloWorldModule.c"])])if __name__ == "__main__":    main()

Nachdem die Namen des Moduls disutils bekannt sind, lässt sich das Paket beschreiben. name steht für den Namen des Pakets. Neben dem Namen des Pakets ist auch der Inhalt des Moduls genau zu spezifizieren. Das erledigt das Attribut ext_modules. Das Paket besteht aus dem gleichnamigen Modul helloWorld, das wiederum aus der C-Datei helloWorldModule.c besteht. Ein Paket kann mehrere Module enthalten.

Mittels Aufruf python setup.py build_ext –inplace lässt sich das Paket bauen.

Bild 2 zeigt die lange Kommandozeile, die notwendig ist, um das Paket auf Linux zu erstellen.

Mit dem Flag –inplace wird in dem aktuellen Verzeichnis eine Shared Library erzeugt, die sich direkt verwenden lässt. Bild 3 stellt die Verwendung des Shared Library auf Linux vor.

Interfaces zu C/C++ mit SWIG erzeugen

Der Simplified Wrapper and Interface Generator (SWIG) erzeugt Interfaces, sodass C beziehungsweise C++ mit anderen Programmiersprachen kommunizieren können. SWIG spricht mehrere Sprachen wie beispielsweise C#, D, Java, JavaScript, Perl, Python, PHP oder Ruby. SWIG dient als Wrapper zwischen Python und C beziehungsweise C++.

Der leichteste Einstieg in SWIG ist es, ein Erweiterungsmodul zu implementieren, was hier mit einem einfachen helloWorld-Beispiel demonstriert wird. Das Erzeugen eines Erweiterungsmoduls mit SWIG beginnt mit einer einfachen SWIG-Interfacedatei, die als hello.i im folgenden Listing dargestellt ist.

%module helloWorld%{#define SWIG_FILE_WITH_INIT#include "helloWorld.h"%}

Die Datei hello.i enthält den Namen des Moduls helloWorld und spezifiziert mit SWIG_FILE_WITH_INIT, dass die zu erzeugende Erweiterung eine Python-Erweiterung ist. Letztere fügt den Initialisierungscode für das Modul hinzu. Außerdem umfasst die Datei die Headerdatei der C-Quellen helloWorld.h und eine Deklaration der C-Funktion namens extern void helloWorld(). Das Kommando swig erzeugt mithilfe der Interfacedatei die zwei Dateien helloWorld_wrap.c und helloWorld.py. Bild 4 zeigt den dabei ablaufenden Build-Prozess.

Während die Datei helloWorld_wrap.c der Low-Level-Wrapper ist, der mit der restlichen Applikation gelinkt wird, enthält die Python-Datei helloWorld.py den High-Level-Code, der sich aus Python importieren lässt. Das Modul benötigt nicht nur die dafür erforderlichen C- und Python-Wrapper, die durch swig erzeugt wurden, sondern auch die eigentliche C-Funktionalität.

Das nächste Listing zeigt die Headerdatei helloWorld.h zu der korrespondierenden Quellcodedatei helloWorld.c:

#include <stdio.h>void helloWorld();

Die Quellcodedatei ist bewusst einfach gehalten.

#include "helloWorld.h"void helloWorld() {    printf("Hello Worldn");}

Jetzt gilt es nur noch, das Erweiterungsmodul helloWorld zu bauen und zu verwenden. Mit dem Python-Modul disutils geht das leicht von der Hand.

C++11 und Python mit pybind11 nahtlos verbinden

Der Name ist Programm, denn pybind11 unterstützt eine nahtlose Zusammenarbeit zwischen C++11 und Python. Nahtlos heißt in dem konkreten Fall, dass sich sowohl C als auch C++ um Python erweitern und andererseits C/C++ in Python einbinden lassen.

pybind11 ist vollständig in die Headerdateien implementiert. Damit steht die gesamte Funktionalität durch das Inkludieren von Headerdateien direkt zur Verfügung.Die Vielseitigkeit von pybind11 ist beeindruckend. So lassen sich Lambda-Ausdrücke verwenden, Funktionen können ihre Argumente per Value, Referenz oder Zeiger erhalten und lassen sich überladen. Klassen können Methoden und Attribute besitzen, lassen sich mehrfach ableiten und erlauben Virtualität. Mit der Standard Template Library (STL) und weiteren Bibliotheken von C++11 lässt pybind praktisch keine Wünsche offen.

Seminar-Tipp: C++11 und C++14

„C++11 feels like a new language“. Dieses berühmte Zitat von Bjarne Stroustrup, dem Vater von C++, bringt es auf den Punkt. Nicht nur der Sprachumfang von 800 Seiten hat sich fast verdoppelt. Auch die Art und Weise, wie Sie in modernes C++ programmieren ist fundamental anders. In dem Seminar lernen Sie, was modernes C++ (C++11 und C++14) auszeichnet. Sie werden die Veränderungen der Kernsprache, die neue Multithreading-Fähigkeit von C++ und die vielen neuen Bibliotheken kennen lernen. Das Seminar „C++11 und C++14“ liefert den Teilnehmern einen praktischen „Leitfaden für Programmierer zu modernem C++“.

Zum Seminar: C++11 und C++14

Die Funktionalität von pybind11 lässt sich am einfachsten an einem Beispiel aufzeigen. Das folgende Listing stellt eine C++-Funktion vor, für die pybind11 eine Python-Bindung erzeugt:

#include <pybind11/pybind11.h>int add(int i, int j) {    return i + j;}PYBIND11_MODULE(function, m) {    m.def("add", &add, "A simple add function");}

Die C++/Python-Bindung besteht aus den folgenden Komponenten

  • #include <pybind11/pybind11.h> erzeugt die C++11/Python-Bindung
  • PYBIND11_MODULE wird durch die import-Anweisung aufgerufen
  • function ist der Name des Erweiterungmoduls, durch das sich das Modul in Python importieren lässt
  • m ist eine Variable vom Typ py::module_, die als Interface für die Bindung verwendet wird
  • m.def macht Python mit der Funktion bekannt und bindet sich an das Erweiterungsmodul function. Dabei ist das erste Argument der Name der Python-Funktion, das zweite die Adresse der C-Funktion und das letzte Argument der Dokumentationsstring der Python-Funktion.

Das Bauen des Programms unter Linux ist mit python3-config fast schon ein Kinderspiel. Zunächst gilt es, die Headerdateien zu ermitteln python3 -m pybind11 -–includes , dann sind mit folgendem Befehl die Suffixe zu bestimmen: python3-config –extension-suffix . Daraus resultieren Kommandozeilenbefehle für das Bauen des Erweiterungsmoduls, und das Ergebnis sollte wie folgt aussehen:
c++ -O3 –Wall –std=c++11 -shared -fPIC $(python3 -m pybind11 –includes) function.cpp -o function$(python3-config –extension-suffix).
Mit den vorgestellten Kommandozeilenbefehlen lässt sich das Modul function erstellen, importieren und verwenden (siehe Bild 5).

Python in C/C++ einbetten

Die Anforderung, Python in C oder C++ einzubetten sind dieselben, die es bei der Erweiterung von Python um C/C++ zu meistern galt. Lediglich die Reihenfolge ist beim Einbetten auf den Kopf gestellt. Zunächst sind die Werte von C/C++ nach Python zu konvertieren. Anschließend gilt es, die konvertierten Werte zum Ausführen der Python-Funktionalität zu verwenden. Zuletzt lassen sich die Ergebnisse dann von Python nach C beziehungsweise C++ konvertieren.

Prinzipiell bieten sich zwei Möglichkeiten an, um Python-Code in C/C++ auszuführen. Zum einen lässt sich der Python-Code als String oder als Modul verpacken und vollständig ausführen. Darüber hinaus ist es möglich, explizit Code aus einem Python-Modul auszuführen. Diese zweite Variante ist deutlich anspruchsvoller und kann daher nicht in diesem Artikel vorgestellt werden.

Die größte Hürde beim Einbetten besteht darin, die richtigen Compiler- und Linkeroptionen zu bestimmen. Mit dem Executable python-config lassen sich die Optionen für den Compiler (python-config –clflags) sowie für den Linker (python-config –ldflags) auf Linux bestimmen.

Das direkte Ausführen eines Python-Strings oder Python-Moduls sollte nun leicht von der Hand gehen.

Python-Strings direkt ausführen

Das einfache C-Programm showTimeString.cpp im folgenden Listing dient als erstes Beispiel.

#include <Python.h>int main(int argc, char* argv[]) {    Py_Initialize();    PyRun_SimpleString("import timen"          "print(time.ctime(time.time()))");    Py_Finalize();}

Mit der Headerdatei <Python.h> stehen die Anweisungen in dem main-Programm zu Verfügung. Py_Initialize initialisiert den Python-Interpreter. PyRun_SimpleString führt den Python-String direkt aus, der zuerst das Modul time lädt, um anschließend die aktuelle Uhrzeit auszugeben. Py_Finalize fährt den Interpreter wieder runter.

Python-Module direkt ausführen

Ähnlich einfach ist das Ausführen eines Python-Moduls in dem folgenden C-Programm. Der Quellcode im folgenden Listing stellt das Python-Modul showTime.py vor.

import timeprint(time.ctime(time.time()))

Ähnlich wie bei dem Python-String im vorherigen Listing importiert das Python-Modul auch das Modul time und stellt die aktuelle Uhrzeit dar. Deutlich komfortabler ist hingegen das C-Programm showTimeModule.cpp im Folgenden, das das Python-Modul lädt und ausführt.

#include <Python.h>#include <stdio.h>int main(int argc, char* argv[]) {    Py_Initialize();    FILE* pyFile = fopen("showTime.py", "r");    if (pyFile) {       PyRun_SimpleFile(pyFile, "showTime.py");       fclose(pyFile);    }    Py_Finalize();}

Das Programm öffnet in diesem Fall die Datei showTime.py und führt das Python-Modul mithilfe des Befehls PyRun_SimpleFile direkt aus (Bild 6).

Persönliches Fazit

Auf die Frage, welche Lösung für das Erweitern von Python um C/C++ zu empfehlen ist, gibt es keine einfache Antwort.

  • Für das Erweitern um eine bestehende dynamische Bibliothek ist das Python-Modul ctypes die erste Wahl.
  • Sollen C beziehungsweise C++ nicht nur mit Python, sondern zudem mit weiteren Skriptsprachen kommunizieren, spielt SWIG seine volle Stärke aus.
  • Den Autor hat pybind11 am stärksten beeindruckt. Mit diesem Framework ist es möglich, C++-Funktionalität mit Python anzusprechen.

Dieser Beitrag stammt mit freundlicher Genehmigung des Autors aus dem Tagungsband des ESE Kongress 2021.

Previous Post

Peloton CEO John Foley Recalls All Fitness Treadmills

Next Post

Apple supplier AT&S is sold out by 2026

admin

admin

Related Posts

How to Grow a YouTube Channel with ScaleLab
IT news

How to Grow a YouTube Channel with ScaleLab: Effective Strategies for Creators

February 4, 2025
Sticker mockups
IT news

Sticker mockups: how to visualize your ideas professionally and efficiently

January 13, 2025
Ways to Get Free Senegal Proxies for Work and Surfing
IT news

Ways to Get Free Senegal Proxies for Work and Surfing

December 24, 2024
Crypto Betting Frontiers
IT news

Crypto Betting Frontiers: The 2025 Landscape

December 6, 2024
iGaming Marketing Trends for 2025
IT news

iGaming Marketing Trends for 2025: Adapting to a Rapidly Changing Landscape

December 5, 2024
Next Post
Apple supplier AT&S is sold out by 2026

Apple supplier AT&S is sold out by 2026

Premium Content

Google Meet Zoom

which platform is the best?

May 5, 2023
Johnson & Johnson is planning the final investigation of the vaccine in September

Johnson & Johnson is planning the final investigation of the vaccine in September

August 21, 2020
NVIDIA launches CloudXR 1.0 SDK to enable streaming services AR/VR in the cloud

NVIDIA launches CloudXR 1.0 SDK to enable streaming services AR/VR in the cloud

August 15, 2020

Browse by Category

  • Games
  • IT news
  • Tech
  • World

VRB News is ready to cooperate with webmasters and content creators. Send an email to info@virtualrealitybrisbane.com

Categories

  • Games
  • IT news
  • Tech
  • World

Recent Posts

  • How to Grow a YouTube Channel with ScaleLab: Effective Strategies for Creators
  • Sticker mockups: how to visualize your ideas professionally and efficiently
  • Ways to Get Free Senegal Proxies for Work and Surfing

© 2023 - The project has been developed ServReality

No Result
View All Result
  • Home
  • About us
  • IT news
  • Tech
  • World
  • Contact

© 2023 - The project has been developed ServReality

Are you sure want to unlock this post?
Unlock left : 0
Are you sure want to cancel subscription?