Vorwort
Jeder weiß, dass die Vorteile von Python eine hohe Entwicklungseffizienz und Benutzerfreundlichkeit sind, während C++ eine hohe Betriebseffizienz aufweist. Die beiden können sich gegenseitig ergänzen in Python Wenn Sie C++-Code in ein Projekt einbetten oder Python zum Implementieren von Peripheriefunktionen in einem C++-Projekt verwenden, müssen Sie möglicherweise C++-Module aufrufen. Hier sind einige grundlegende Methoden zum Exportieren von C++-Code in Python-Schnittstellen zusammen. .
Originalexport
Der Python-Interpreter ist in C implementiert, sofern unsere C++-Datenstruktur von Python verstanden werden kann Theoretisch kann es direkt aufgerufen werden. Wir implementieren test1.cpp wie folgt
#include <Python.h> int Add(int x, int y) { return x + y; } int Del(int x, int y) { return x - y; } PyObject* WrappAdd(PyObject* self, PyObject* args) { int x, y; if (!PyArg_ParseTuple(args, "ii", &x, &y)) { return NULL; } return Py_BuildValue("i", Add(x, y)); } PyObject* WrappDel(PyObject* self, PyObject* args) { int x, y; if (!PyArg_ParseTuple(args, "ii", &x, &y)) { return NULL; } return Py_BuildValue("i", Del(x, y)); } static PyMethodDef test_methods[] = { {"Add", WrappAdd, METH_VARARGS, "something"}, {"Del", WrappDel, METH_VARARGS, "something"}, {NULL, NULL} }; extern "C" void inittest1() { Py_InitModule("test1", test_methods); }
Der Kompilierungsbefehl lautet wie folgt
g++ -fPIC -shared test1.cpp -I/usr/include/python2.6 -o test1.so
Führen Sie den Python-Interpreter aus und testen Sie ihn wie folgt
>>> import test1 >>> test1.Add(1,2) 3
Hier sind einige Punkte zu beachten
Wenn der Name der generierten dynamischen Bibliothek test1 ist, muss die Quelldatei die Funktion inittest1 haben und der erste Parameter von Py_InitModule muss „test1“ sein, andernfalls Python Das Importieren des Moduls schlägt fehl
Wenn es sich um eine CPP-Quelldatei handelt, muss die Funktion inittest1 mit extern „C“ geändert werden. Wenn es sich um eine C-Quelldatei handelt, ist sie nicht erforderlich. Der Grund dafür ist, dass der Python-Interpreter beim Importieren von Bibliotheken nach Funktionen wie initxxx sucht und C++ Funktionssymbole unterschiedlich codiert. C++ berücksichtigt beim Codieren von Funktionssymbolen insbesondere die Funktion nm test1.so
Die Funktionssymbole. Das C++-Filtertool kann den Funktionsprototyp durch die durch Boost implementierten Symbole
invertieren > Wir verwenden das gleiche Beispiel wie oben, um test2.cpp wie folgt zu implementieren
#include <boost/python/module.hpp> #include <boost/python/def.hpp> using namespace boost::python; int Add(const int x, const int y) { return x + y; } int Del(const int x, const int y) { return x - y; } BOOST_PYTHON_MODULE(test2) { def("Add", Add); def("Del", Del); }
g++ test2.cpp -fPIC -shared -o test2.so -I/usr/include/python2.6 -I/usr/local/include -L/usr/local/lib -lboost_python
muss beim Kompilieren den Boost-Header angeben. Die Pfade von Dateien und Bibliotheken sind hier /usr/local/include und /usr/local/lib oder exportieren Sie das Modul über setup.py
#!/usr/bin/env python from distutils.core import setup from distutils.extension import Extension setup(name="PackageName", ext_modules=[ Extension("test2", ["test2.cpp"], libraries = ["boost_python"]) ])
python setup.py build
>>> import test2 >>> test2.Add(1,2) 3 >>> test2.Del(1,2) -1
test3.cpp wird wie folgt implementiert
#include <boost/python.hpp> using namespace boost::python; class Test { public: int Add(const int x, const int y) { return x + y; } int Del(const int x, const int y) { return x - y; } }; BOOST_PYTHON_MODULE(test3) { class_<Test>("Test") .def("Add", &Test::Add) .def("Del", &Test::Del); }
BOOST_PYTHON_MODULE Die Verwendung von .def ähnelt in gewisser Weise der Python-Syntax, die äquivalent zu
< ist 🎜>
Der Kompilierungsbefehl lautet wie folgtclass_<Test>("Test").def("Add", &Test::Add); class_<Test>("Test").def("Del", &Test::Del);
g++ test3.cpp -fPIC -shared -o test3.so -I/usr/include/python2.6 -I/usr/local/include/boost -L/usr/local/lib -lboost_python
>>> import test3 >>> test = test3.Test() >>> test.Add(1,2) 3 >>> test.Del(1,2) -1
Variable Parameterfunktion exportieren
test4.cpp wird wie folgt implementiert
#include <boost/python.hpp> using namespace boost::python; class Test { public: int Add(const int x, const int y, const int z = 100) { return x + y + z; } }; int Del(const int x, const int y, const int z = 100) { return x - y - z; } BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(Add_member_overloads, Add, 2, 3) BOOST_PYTHON_FUNCTION_OVERLOADS(Del_overloads, Del, 2, 3) BOOST_PYTHON_MODULE(test4) { class_<Test>("Test") .def("Add", &Test::Add, Add_member_overloads(args("x", "y", "z"), "something")); def("Del", Del, Del_overloads(args("x", "y", "z"), "something")); }
Der Kompilierungsbefehl lautet wie folgt
Der Test ist wie folgtg++ test4.cpp -fPIC -shared -o test4.so -I/usr/include/python2.6 -I/usr/local/include/boost -L/usr/local/lib -lboost_python
>>> import test4 >>> test = test4.Test() >>> print test.Add(1,2) 103 >>> print test.Add(1,2,z=3) 6 >>> print test4.Del(1,2) -1 >>> print test4.Del(1,2,z=3) -1
Exportschnittstelle mit Python-Objekten
Seitdem Wenn es als Python-Schnittstelle exportiert wird, verwendet der Aufrufer zwangsläufig Python-spezifische Datenstrukturen wie Tupel, Liste und Diktat. Da die ursprüngliche ökologische Methode zu mühsam ist, wird hier nur die Verwendung von Boost aufgezeichnet Ich möchte die folgende Python-Funktion
def Square(list_a) { return [x * x for x in list_a] }
Der Code lautet wie folgt
Der Kompilierungsbefehl lautet wie folgt#include <boost/python.hpp> boost::python::list Square(boost::python::list& data) { boost::python::list ret; for (int i = 0; i < len(data); ++i) { ret.append(data[i] * data[i]); } return ret; } BOOST_PYTHON_MODULE(test5) { def("Square", Square); }
Der Test ist wie folgt
g++ test5.cpp -fPIC -shared -o test5.so -I/usr/include/python2.6 -I/usr/local/include/boost -L/usr/local/lib -lboost_python
>>> import test5 >>> test5.Square([1,2,3]) [1, 4, 9]
,
, und die Verwendungsmethode stimmt im Wesentlichen mit Python überein. Für bestimmte Methoden können Sie boost/python/tuple.hpp und andere entsprechende Dateien in der Boost-Header-Datei anzeigenboost::python::tuple
Eine weitere häufig verwendete Funktion ist boost::python::list
, und die Verwendungsmethode ist wie folgt boost::python::dict
boost::python::make_tuple()
boost::python::tuple(int a, int b, int c) { return boost::python::make_tuple(a, b, c); }