Führen Sie Python-Code unter C ++ aus (mit Boost.Python).

Einführung

Boost.Python wird häufig beim Erstellen einer Bibliothek für Python mit C ++ verwendet, kann aber auch zum sogenannten "Einbetten" verwendet werden, bei dem Python-Code von C ++ verwendet wird.

Gibt es nicht viel Nachfrage nach Python-Code aus C ++? Selbst wenn Sie nach "Boost Python" usw. suchen, erhalten Sie nur Artikel über die entgegengesetzte Verwendung (bei Verwendung von C ++ - Code aus Python). In diesem Fall ist der Artikel beim Einbetten von Python in C ++ leicht zu finden, wenn Sie das Suchwort "einbetten" (eingebettet) eingeben.

Einfachstes Codebeispiel

main.cpp


#include <boost/python.hpp>
namespace py = boost::python;

int main()
{
    Py_Initialize(); //Muss zuerst angerufen werden

    try
    {
        //"Drucken" in Python('Hello World!')Ausführen
        py::object global = py::import("__main__").attr("__dict__");
        py::exec("print('Hello World!')", global);
    }
    catch (const py::error_already_set &)
    {
        //Zeigen Sie Fehlerdetails an, wenn beim Ausführen von Python-Code ein Fehler auftritt
        PyErr_Print();
    }

    return 0;
}

In diesem Beispiel wird die Funktion py :: exec () verwendet, um einfach den Python-Code print ('Hello World!') Auszuführen. Ich führe meinen Code im globalen Namespace von Python aus, indem ich ein Objekt im globalen Namespace von Python in einer Variablen namens "global" abrufe.

Boost.Python ruft die C-Oberfläche von Python hinter den Kulissen auf. Sie müssen daher die Funktion "Py_Initialize ()" aufrufen, bevor Sie sie verwenden können. (* Laut offiziellem Tutorial sollte "Py_Finalize ()" im Code nicht aufgerufen werden.)

Wenn in Python ein Laufzeitfehler auftritt, wird eine Ausnahme vom Typ "py :: error_already_set" ausgelöst, sodass dieser abgefangen wird und der Inhalt mit "PyErr_Print ()" angezeigt wird.

Kompilieren (für Linux + GCC)

Für Linux + GCC können Sie mit dem folgenden Befehl kompilieren.

Wie zu kompilieren


$ g++ main.cpp `pkg-config python3-embed --cflags --libs` -lboost_python38

Abhängig von der Umgebung gibt es möglicherweise eine Version ohne "python3-embedded". Ändern Sie sie daher entsprechend in "pkg-config python3" (in der Version mit "python3-embedded" ist die Bibliothek zum Einbetten vom Original ausgeschlossen Daher kann die Verwendung von "pkg-config python3" zu einem Verbindungsfehler führen.

Außerdem hängt der Teil "boost_python38" von der Version und der Umgebung ab (möglicherweise im Format "boost_python-py38").

Wenn Sie den Namen der Boost.Python-Bibliothek, zu der eine Verknüpfung hergestellt werden soll, nicht kennen, können Sie ihn mit dem folgenden Befehl nachschlagen: Der ** Teil von lib **. Also, der angezeigt wird, ist der Bibliotheksname.

Boost.So finden Sie heraus, ob Sie den Namen der Python-Bibliothek nicht kennen


$ ldconfig -p | grep "boost_python3"

Grundlegende Verwendung

Von hier aus werden wir uns ansehen, wie die einzelnen Funktionen verwendet werden.

Unter der Annahme, dass "Namespace py = boost :: python;" geschrieben ist, wird es im Folgenden als "py" geschrieben. Außerdem ist "global" im Code dasselbe wie im ersten Beispiel, es ist ein Objekt des globalen Namespace, der durch den folgenden Code erhalten wird.

py::object global = py::import("__main__").attr("__dict__");

py :: eval (): Bewerten Sie den Ausdruck in Python und geben Sie das Ergebnis zurück

Wenn Sie einen Python-Ausdruck als Zeichenfolge angeben, wird das Ergebnis als Typ "py :: object" zurückgegeben. Sie können das Ergebnis als C ++ - Typ erhalten, indem Sie es wie unten gezeigt mit py :: extract <Typname> kombinieren.

// "2**3"Holen Sie sich das Ergebnis von
py::object result = py::eval("2**3", global);

//Konvertieren Sie das Ergebnis in den Typ int und geben Sie es aus
std::cout << py::extract<int>(result) << std::endl;

Ausführungsergebnis


8

In diesem Beispiel werden die Funktionen in Python nicht speziell verwendet. Selbst wenn der Namespace "global" des zweiten Arguments weggelassen wird, funktioniert dies. Beachten Sie jedoch, dass Sie, wenn Sie das zweite Argument weglassen, keine in Python integrierten Funktionen wie "pow" oder Variablen / Funktionen verwenden können, die Sie separat definiert haben.

py :: exec (): Übergeben Sie Python-Code als Zeichenfolge und führen Sie ihn aus

Wie im ersten Beispiel wird der Python-Code so ausgeführt, wie er ist, wenn Sie der Funktion py :: exec () den Python-Code als Zeichenfolge geben. Im Gegensatz zu py :: eval () kann es auch mehrere durch Zeilenumbrüche getrennte Befehle ausführen und Klassen definieren.

py::exec(
    "print('Hello!')\n"
    "print('World!')", global);

Ausführungsergebnis


Hello!
World!

Wenn eine neue Variable erstellt wird, wird sie im im zweiten Argument angegebenen Namespace generiert.

//2, um eine Variable im globalen Namespace von Python zu erhalten**Ersatz 3
py::exec("result = 2**3", global);

//Konvertieren Sie das Ergebnis in den Typ int und geben Sie es aus
std::cout << py::extract<int>(global["result"]) << std::endl;

Ausführungsergebnis


8

py :: exec_file (): Führen Sie Python-Code aus einer Datei aus

Sie können py :: exec_file () verwenden, um den Inhalt der Datei zu lesen und wie py :: exec () auszuführen. Das erste Argument ist der Dateipfad zum Python-Skript.

py::exec_file("hello.py", global);

Dies ist nützlich, wenn Sie die Definition Ihrer eigenen Klasse als Python-Skriptdatei getrennt von C ++ vorbereiten möchten.

py :: object :: attr (): Objektfeld- / Methodenreferenz

Felder (Mitgliedsvariablen) und Methoden (Mitgliedsfunktionen) von py :: object können mit der Funktion attr () verwendet werden.

Beispiel für den Aufruf der Join-Methode vom Typ str


// ['hoge','fuga','piyo']Erstellen Sie eine Liste mit dem Namen
py::object list = py::eval("['hoge','fuga','piyo']", global);

// 「','.join(list)Und kombinieren Sie die Zeichenfolgen in der Liste durch Kommas getrennt
py::object result = py::object(",").attr("join")(list);

//Konvertieren Sie das Ergebnis in Zeichenfolgentyp und Ausgabe
std::string resultStr = py::extract<std::string>(result);
std::cout << resultStr << std::endl;

Ausführungsergebnis


hoge,fuga,piyo

py :: import (): Verwendung der Python-Bibliothek

Sie können py :: import verwenden, um eine Bibliothek auf die gleiche Weise wie Pythons import-Anweisung zu importieren.

py::object np = py::import("numpy");

Schreiben wir als Beispiel den folgenden Python-Code in C ++, ohne py :: exec () zu verwenden. Dies ist ein Beispiel zur Anzeige des Graphen von y = x ^ 2 mit matplotlib.

Python-Codebeispiel


import numpy as np
import matplotlib.pyplot as plt

x = np.arange(-10, 10, 0.1)
y = x ** 2
plt.plot(x, y)
plt.show()

Boost oben.C mit Python++Probe geschrieben in


py::object np = py::import("numpy");
py::object plt = py::import("matplotlib.pyplot");

py::object x = np.attr("arange")(-10, 10, 0.1);
py::object y = x * x;
plt.attr("plot")(x, y);
plt.attr("show")();

(Da x ** 2 nicht wie auf der C ++ - Seite geschrieben werden kann, wird es stattdessen auf x * x gesetzt.)

Bei der Ausführung wird das Diagramm wie unten gezeigt in matplotlib angezeigt. y=x^2のグラフ

Referenz

Recommended Posts

Führen Sie Python-Code unter C ++ aus (mit Boost.Python).
Führen Sie Python-Code über die C # -GUI aus
Online-Übertragung mit Python
[Schatzdaten] [Python] Führen Sie mit dem TD-Client eine Abfrage zu Schatzdaten aus.
C-Code-Überprüfungstool mit pycparser
Hinweise zur Verwendung von MeCab aus Python
Studie über die Miete in Tokio mit Python (3-2)
Hinweise zur Installation von Python mit PyEnv
Überprüfen Sie den Python-Codestil mit pep8
Hinweise zur Verwendung von rstrip mit Python.
Installieren Sie Python unter CentOS mit Pyenv
Studie über die Miete in Tokio mit Python (3-3)
Installieren Sie Python unter CentOS mit pyenv
Rufen Sie C / C ++ von Python auf dem Mac auf
Erstellen Sie mit Boost.Python einen C-Sprach-Wrapper
Hinweise zur Verwendung von OpenCV mit Windows 10 Python 3.8.3.
Erkennen Sie "Helligkeit" mit Python auf Raspberry Pi 3!
Schreiben Sie testgetriebenen FizzBuzz-Code mit Python doctest.
Holen Sie sich Python-Quellcode-Metriken mit Radon
Installieren Sie die Python-Bibliothek auf Lambda mit [/ tmp]
[C] [Python] Lesen mit AquesTalk unter Linux
Doppelte Kombinationen auflisten (C ++) → Python-Code hinzufügen
Lassen Sie einen Servomotor mit Python auf Raspberry Pi 3 laufen
Studie über die Miete in Tokio mit Python (3-1 von 3)
Führen Sie Python-Code in der A2019 Community Edition aus
Ermitteln Sie die Temperatur mit Python auf Raspberry Pi 3!
[Hinweis] Führen Sie Python-Code aus Excel aus (xlwings)
Führen Sie Python in C ++ unter Visual Studio 2017 aus
python setup.py testet den Code mit Multiprocess
Erstellen Sie die Python3.5 + matplotlib-Umgebung unter Ubuntu 12 mit Anaconda
Python unter Windows
Erkennen Sie Schiebeschalter mit Python auf Raspberry Pi 3!
Twitter mit Python3
Hinweise zur Installation von Python3 und zur Verwendung von pip unter Windows7
[Python] Lassen Sie uns das Modul regelmäßig nach Zeitplan ausführen
Versuchen Sie, QR-Code mit Raspberry Pi zu verwenden
Führen Sie Python YOLOv3 in C ++ unter Visual Studio 2017 aus
Installieren Sie Python 3.8.6 unter macOS BigSur mit pyenv
Python: Versuchen Sie, die Benutzeroberfläche von Pythonista 3 auf dem iPad zu verwenden
Python-Entwicklung unter Ubuntu unter AWS EC2 (mit Jupyter Lab)
Debuggen mit VS-Code mit Boost Python Numpy
Starten Sie Python
Erkennen Sie Magnetschalter mit Python auf Raspberry Pi 3!
Hinweise zur Verwendung von dict mit Python [Competition Pro]
Python-Zeichencode
Führen Sie Python Script regelmäßig in der AWS Data Pipeline aus
Hinweis zur Codierung bei LANG = C in Python
Python C ++ Notizen
Probieren Sie CI den Push-Python-Code auf GitHub aus.
Python auf Mac
Python, openFrameworks (c ++)
[Node-RED] Führen Sie Python in einer virtuellen Anaconda-Umgebung von Node-RED aus [Anaconda] [Python]
[Python] Code, der Algorithmen kennt
Lassen Sie den Summer mit Python auf Raspberry Pi 3 erklingen!
Python auf Windbg