Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
In dit artikel bouwt u een C++-extensiemodule voor CPython om een hyperbolische tangens te berekenen en aan te roepen vanuit Python-code. De routine wordt eerst geïmplementeerd in Python om de relatieve prestatiewinst van het implementeren van dezelfde routine in C++te demonstreren.
Codemodules die zijn geschreven in C++ (of C) worden vaak gebruikt om de mogelijkheden van een Python-interpreter uit te breiden. Er zijn drie primaire typen uitbreidingsmodules:
- Accelerator-modules: Versnelde prestaties inschakelen. Omdat Python een geïnterpreteerde taal is, kunt u een acceleratormodule schrijven in C++ voor hogere prestaties.
- Wrapper-modules: stel bestaande C/C++-interfaces beschikbaar voor Python-code of maak een meer python-achtige API beschikbaar die eenvoudig te gebruiken is vanuit Python.
-
Modules voor systeemtoegang op laag niveau: Maak systeemtoegangsmodules om functies op lager niveau van de
CPython
runtime, het besturingssysteem of de onderliggende hardware te bereiken.
In dit artikel ziet u twee manieren om een C++-extensiemodule beschikbaar te maken voor Python:
- Gebruik de standaardextensies
CPython
, zoals beschreven in de Python-documentatie. - Gebruik PyBind11, die we aanbevelen voor C++11 vanwege de eenvoud. Zorg ervoor dat u werkt met een van de recentere versies van Python om compatibiliteit te garanderen.
Het voltooide voorbeeld voor dit scenario is beschikbaar op GitHub via python-samples-vs-cpp-extension.
Vereiste voorwaarden
Visual Studio 2017 of hoger, waarbij de Python-ontwikkelworkload is geïnstalleerd. De workload bevat de systeemeigen Python-ontwikkelhulpprogramma's, waarmee de C++-workload en -hulpprogramma's worden toegevoegd die nodig zijn voor systeemeigen extensies.
Zie Python-ondersteuning voor Visual Studio installeren voor meer informatie over de installatieopties.
Opmerking
Wanneer u de workload data science- en analytische toepassingen installeert, worden Python en de systeemeigen ontwikkelhulpprogramma's van Python standaard geïnstalleerd.
Als u Python afzonderlijk installeert, zorg ervoor dat u de optie om foutopsporingssymbolen te downloaden selecteert onder Geavanceerde opties in het Python-installatieprogramma. Deze optie is vereist voor het gebruik van foutopsporing in de gemengde modus tussen uw Python-code en systeemeigen code.
De Python-toepassing maken
Volg deze stappen om de Python-toepassing te maken.
Maak een nieuw Python-project in Visual Studio door Bestand>nieuw>project te selecteren.
Zoek in het dialoogvenster Een nieuw project maken naar Python. Selecteer de Python-toepassingssjabloon en selecteer Volgende.
Voer een projectnaam en locatie in en selecteer Maken.
Visual Studio maakt het nieuwe project. Het project wordt geopend in Solution Explorer en het projectbestand (.py) wordt geopend in de code-editor.
Plak de volgende code in het bestand .py . Als u enkele van de python-bewerkingsfuncties wilt ervaren, voert u de code handmatig in.
Met deze code wordt een hyperbolische tangens berekend zonder de wiskundige bibliotheek te gebruiken. Dit is wat u later versnelt met systeemeigen Python-extensies.
Aanbeveling
Schrijf uw code in pure Python voordat u deze herschrijft in C++. Op deze manier kunt u eenvoudiger controleren of uw systeemeigen Python-code juist is.
from random import random from time import perf_counter # Change the value of COUNT according to the speed of your computer. # The value should enable the benchmark to complete in approximately 2 seconds. COUNT = 500000 DATA = [(random() - 0.5) * 3 for _ in range(COUNT)] e = 2.7182818284590452353602874713527 def sinh(x): return (1 - (e ** (-2 * x))) / (2 * (e ** -x)) def cosh(x): return (1 + (e ** (-2 * x))) / (2 * (e ** -x)) def tanh(x): tanh_x = sinh(x) / cosh(x) return tanh_x def test(fn, name): start = perf_counter() result = fn(DATA) duration = perf_counter() - start print('{} took {:.3f} seconds\n\n'.format(name, duration)) for d in result: assert -1 <= d <= 1, " incorrect values" if __name__ == "__main__": print('Running benchmarks with COUNT = {}'.format(COUNT)) test(lambda d: [tanh(x) for x in d], '[tanh(x) for x in d] (Python implementation)')
Voer het programma uit door Foutopsporing>starten te selecteren zonder foutopsporing of selecteer de sneltoets Ctrl+F5.
Er wordt een opdrachtvenster geopend om de programma-uitvoer weer te geven.
In de uitvoer ziet u de hoeveelheid tijd die is gerapporteerd voor het benchmarkproces.
Voor deze handleiding duurt het benchmarkproces ongeveer 2 seconden.
Pas indien nodig de waarde van de
COUNT
variabele in de code aan zodat de benchmark binnen ongeveer 2 seconden op uw computer kan worden voltooid.Voer het programma opnieuw uit en bevestig dat de gewijzigde
COUNT
waarde de benchmark binnen ongeveer 2 seconden produceert.
Aanbeveling
Wanneer u benchmarks uitvoert, gebruikt u altijd de optie Foutopsporing>starten zonder foutopsporing . Met deze methode voorkomt u de overhead die kan optreden wanneer u de code uitvoert in het Foutopsporingsprogramma van Visual Studio.
De C++-kernprojecten maken
Volg deze stappen om twee identieke C++-projecten te maken, superfastcode en superfastcode2. Later gebruikt u een andere benadering in elk project om de C++-code beschikbaar te maken voor Python.
Klik in Solution Explorer met de rechtermuisknop op de naam van de oplossing en selecteerNieuw project>.
Een Visual Studio-oplossing kan zowel Python- als C++-projecten bevatten. Dit is een van de voordelen van het gebruik van Visual Studio voor Python-ontwikkeling.
Stel in het dialoogvenster Een nieuw project toevoegen het taalfilter in op C++en voer leegin het zoekvak in.
Selecteer Leeg project in de lijst met projectsjabloonresultaten en selecteer Volgende.
Voer in het dialoogvenster Uw nieuwe project configureren de projectnaam in:
- Voer voor het eerste project de naam superfastcode in.
- Voer voor het tweede project de naam superfastcode2 in.
Klik op Creëren.
Herhaal deze stappen en maak twee projecten.
Aanbeveling
Er is een alternatieve benadering beschikbaar wanneer u de systeemeigen Python-ontwikkelhulpprogramma's hebt geïnstalleerd in Visual Studio. U kunt beginnen met de python-extensiemodulesjabloon , waarmee veel van de stappen die in dit artikel worden beschreven, vooraf worden voltooid.
Voor de stapsgewijze instructies in dit artikel is het nuttig om te beginnen met een leeg project, zodat we kunnen laten zien hoe u stapsgewijs de extensiemodule bouwt. Nadat u het proces hebt begrepen, kunt u de alternatieve sjabloon gebruiken om tijd te besparen wanneer u uw eigen extensies schrijft.
C++ bestand toevoegen aan project
Voeg vervolgens een C++-bestand toe aan elk project.
Vouw in Solution Explorer het project uit, klik met de rechtermuisknop op het knooppunt Bronbestanden en selecteerNieuw item>.
Selecteer C++-bestand (.cpp) in de lijst met bestandssjablonen.
Voer de naam voor het bestand in als module.cpp en selecteer vervolgens Toevoegen.
Belangrijk
Zorg ervoor dat de bestandsnaam de .cpp extensie bevat. Visual Studio zoekt naar een bestand met de .cpp-extensie om weergave van de eigenschappenpagina's van het C++-project mogelijk te maken.
Vouw op de werkbalk het vervolgkeuzemenu Configuratie uit en selecteer uw doelconfiguratietype:
- Activeer de x64-configuratie voor een 64-bits Python-runtime.
- Activeer de Win32-configuratie voor een 32-bits Python-runtime.
Herhaal deze stappen voor beide projecten.
Projecteigenschappen configureren
Voordat u code toevoegt aan de nieuwe C++-bestanden, configureert u de eigenschappen voor elk C++-moduleproject en test u de configuraties om te controleren of alles werkt.
U moet de projecteigenschappen instellen voor zowel de foutopsporings- als release-buildconfiguraties van elke module.
Klik in Solution Explorer met de rechtermuisknop op het C++-moduleproject (superfastcode of superfastcode2) en selecteer Eigenschappen.
Configureer de eigenschappen voor de foutopsporingsbuild van de module en configureer vervolgens dezelfde eigenschappen voor de release-build :
Configureer bovenaan het dialoogvenster Eigenschappenpagina's van het project de volgende opties voor bestandsconfiguratie:
Voor de Configuratie selecteer Debug of Release. (Mogelijk ziet u deze opties met het actieve voorvoegsel.)
Voor het platform selecteert u Actief (x64) of Actief (Win32), afhankelijk van uw selectie in de vorige stap.
Opmerking
Wanneer u uw eigen projecten maakt, moet u de foutopsporings - en releaseconfiguraties afzonderlijk configureren op basis van uw specifieke scenariovereisten. In deze oefening stelt u de configuraties in voor het gebruik van een release-build van CPython. Met deze configuratie worden enkele foutopsporingsfuncties van de C++-runtime uitgeschakeld, waaronder asserties. Voor het gebruik van binaire CPython-foutopsporingsbestanden (python_d.exe) zijn verschillende instellingen vereist.
Stel andere projecteigenschappen in zoals beschreven in de volgende tabel.
Als u een eigenschapswaarde wilt wijzigen, voert u een waarde in het eigenschapsveld in. Voor sommige velden kunt u de huidige waarde selecteren om een vervolgkeuzelijst met opties uit te vouwen of een dialoogvenster openen om de waarde te definiëren.
Nadat u waarden op een tabblad hebt bijgewerkt, selecteert u Toepassen voordat u overschakelt naar een ander tabblad. Deze actie helpt ervoor te zorgen dat uw wijzigingen behouden blijven.
Tabblad en sectie Vastgoed Waarde Configuratie-eigenschappen>Algemeen Doelnaam Geef de naam op van de module om ernaar te verwijzen vanuit Python in from...import
instructies, zoals superfaste code. U gebruikt dezelfde naam in de C++-code wanneer u de module voor Python definieert. Als u de naam van het project wilt gebruiken als modulenaam, laat u de standaardwaarde $<ProjectName> staan. Voegpython_d.exe
aan het einde van de naam van_d
toe.Configuratietype Dynamische bibliotheek (.dll) Configuratie-eigenschappen>Geavanceerd Doelbestandsextensie .pyd (Python Extension Module) C/C++>Algemeen Extra inclusie directories Voeg de include-map van Python toe die bij uw installatie past (bijvoorbeeld c:\Python36\include). C/C++>Preprocessor Preprocessordefinities Als deze aanwezig is, wijzigt u de _DEBUG waarde in NDEBUG zodat deze overeenkomt met de niet-foutopsporingsversie van CPython. Laat deze waarde ongewijzigd wanneer u python_d.exegebruikt. C/C++>Codegeneratie Runtime-bibliotheek DLL met meerdere threads (/MD) om overeen te komen met de releaseversie (zonder debugmodus) van CPython. Wanneer u python_d.exegebruikt, laat u deze waarde staan als DLL met meerdere threads voor foutopsporing (/MDd). Basisuitvoeringstijdcontroles standaard Linker>Algemeen Aanvullende bibliotheekmappen Voeg de map Python-bibliotheken toe die .lib-bestanden bevat, zoals geschikt voor uw installatie (bijvoorbeeld c:\Python36\bibliotheken). Zorg ervoor dat u verwijst naar de libs-map die .lib-bestanden bevat en niet naar de Lib-map die .py-bestanden bevat. Belangrijk
Als het tabblad C/C++ niet wordt weergegeven als optie voor de projecteigenschappen, bevat het project geen codebestanden die Visual Studio identificeert als C/C++-bronbestanden. Deze voorwaarde kan optreden als u een bronbestand maakt zonder . c of .cpp bestandsextensie.
Als u per ongeluk module.coo hebt ingevoerd in plaats van module.cpp bij het maken van het C++-bestand, maakt Visual Studio het bestand, maar stelt het bestandstype niet in op C/C+ compiler. Dit bestandstype is nodig om de aanwezigheid van het tabblad C/C++-eigenschappen te activeren in het dialoogvenster projecteigenschappen. De misidentificatie blijft behouden, zelfs als u de naam van het codebestand wijzigt met een .cpp bestandsextensie.
Als u het codebestandstype correct wilt instellen, klikt u in Solution Explorer met de rechtermuisknop op het codebestand en selecteert u Eigenschappen. Selecteer voor het itemtypede C/C++-compiler.
Nadat u alle eigenschappen hebt bijgewerkt, selecteert u OK.
Herhaal de stappen voor de andere buildconfiguratie.
Test uw huidige configuratie. Herhaal de volgende stappen voor zowel de foutopsporing als de release-builds van beide C++-projecten.
Code en testconfiguratie toevoegen
U bent nu klaar om code toe te voegen aan uw C++-bestanden en de release-build te testen.
Open het bestand module.cpp in de code-editor voor het superfastcode C++-project.
Plak in het bestand module.cpp de volgende code:
#include <Windows.h> #include <cmath> const double e = 2.7182818284590452353602874713527; double sinh_impl(double x) { return (1 - pow(e, (-2 * x))) / (2 * pow(e, -x)); } double cosh_impl(double x) { return (1 + pow(e, (-2 * x))) / (2 * pow(e, -x)); } double tanh_impl(double x) { return sinh_impl(x) / cosh_impl(x); }
Sla uw wijzigingen op.
Bouw de releaseconfiguratie voor het C++-project om te bevestigen dat uw code juist is.
Herhaal de stappen om code toe te voegen aan het C++-bestand voor het superfastcode2-project en test de release-build .
C++-projecten converteren naar Python-extensies
Als u de C++ DLL een extensie voor Python wilt maken, wijzigt u eerst de geëxporteerde methoden om te communiceren met Python-typen. Voeg vervolgens een functie toe om de module te exporteren, samen met definities voor de methoden van de module.
In de volgende secties ziet u hoe u de extensies maakt met behulp van de CPython-extensies en PyBind11. Het superfasctcode-project maakt gebruik van de CPython-extensies en het superfasctcode2-project implementeert PyBind11.
CPython-extensies gebruiken
Zie de naslaghandleiding voor Python/C API, met name de pagina Moduleobjecten voor meer informatie over de code die in deze sectie wordt gepresenteerd. Wanneer u de referentie-inhoud bekijkt, moet u uw versie van Python selecteren in de vervolgkeuzelijst rechtsboven.
Open het bestand module.cpp in de code-editor voor het superfastcode C++-project.
Voeg boven aan het module.cpp-bestand een instructie toe om het python.h-headerbestand op te nemen:
#include <Python.h>
Vervang de
tanh_impl
methodecode om Python-typen te accepteren en te retourneren (dat wil gezegd: aPyObject*
):PyObject* tanh_impl(PyObject* /* unused module reference */, PyObject* o) { double x = PyFloat_AsDouble(o); double tanh_x = sinh_impl(x) / cosh_impl(x); return PyFloat_FromDouble(tanh_x); }
Voeg aan het einde van het bestand een structuur toe om te definiëren hoe de C++
tanh_impl
-functie aan Python moet worden weergegeven:static PyMethodDef superfastcode_methods[] = { // The first property is the name exposed to Python, fast_tanh // The second is the C++ function with the implementation // METH_O means it takes a single PyObject argument { "fast_tanh", (PyCFunction)tanh_impl, METH_O, nullptr }, // Terminate the array with an object containing nulls { nullptr, nullptr, 0, nullptr } };
Voeg nog een structuur toe om te definiëren hoe u naar de module in uw Python-code verwijst, met name wanneer u de
from...import
instructie gebruikt.De naam die in deze code wordt geïmporteerd, moet overeenkomen met de waarde in de projecteigenschappen onderAlgemene>doelnaam voor >.
In het volgende voorbeeld betekent de
"superfastcode"
naam dat u defrom superfastcode import fast_tanh
instructie in Python kunt gebruiken omdatfast_tanh
deze is gedefinieerd insuperfastcode_methods
. Bestandsnamen die intern zijn voor het C++-project, zoals module.cpp, zijn inconsequent.static PyModuleDef superfastcode_module = { PyModuleDef_HEAD_INIT, "superfastcode", // Module name to use with Python import statements "Provides some functions, but faster", // Module description 0, superfastcode_methods // Structure that defines the methods of the module };
Voeg een methode toe die door Python wordt aangeroepen wanneer de module wordt geladen. De naam van de methode moet
PyInit_<module-name>
zijn, waarbij de <modulenaam> exact overeenkomt met de eigenschap Configuratie-eigenschappen>Algemeen>Doelnaam van het C++-project. Dat wil gezegd, de naam van de methode komt overeen met de bestandsnaam van het PYD-bestand dat door het project is gebouwd.PyMODINIT_FUNC PyInit_superfastcode() { return PyModule_Create(&superfastcode_module); }
Bouw het C++-project en verifieer uw code. Als er fouten optreden, raadpleegt u de sectie 'Compileerfouten oplossen' .
PyBind11 gebruiken
Als u de stappen in de vorige sectie voor het superfastcodeproject uitvoert, ziet u mogelijk dat voor de oefening standaardcode is vereist om de modulestructuren voor C++ CPython-extensies te maken. In deze oefening ontdekt u dat PyBind11 het coderingsproces vereenvoudigt. U gebruikt macro's in een C++-headerbestand om hetzelfde resultaat te bereiken, maar met veel minder code. Er zijn echter extra stappen vereist om ervoor te zorgen dat Visual Studio de PyBind11-bibliotheken kan vinden en bestanden kan opnemen. Zie De basisbeginselen van PyBind11 voor meer informatie over de code in deze sectie.
PyBind11 installeren
De eerste stap is het installeren van PyBind11 in uw projectconfiguratie. In deze oefening gebruikt u het Venster Developer PowerShell .
Open het Hulpprogramma's>Opdrachtregel>PowerShell voor ontwikkelaars venster.
Installeer PyBind11 in het Venster Developer PowerShell met behulp van de pip-opdracht
pip install pybind11
ofpy -m pip install pybind11
.Visual Studio installeert PyBind11 en de afhankelijke pakketten.
PyBind11-paden toevoegen aan project
Nadat PyBind11 is geïnstalleerd, moet u de PyBind11-paden toevoegen aan de eigenschap Additional Include Directories voor het project.
Voer in Developer PowerShell het venster de opdracht
python -m pybind11 --includes
ofpy -m pybind11 --includes
.Met deze actie wordt een lijst afgedrukt met PyBind11-paden die u moet toevoegen aan uw projecteigenschappen.
Markeer de lijst met paden in het venster en selecteer Kopiëren (dubbele pagina) op de werkbalk van het venster.
De lijst met samengevoegde paden wordt toegevoegd aan het Klembord.
Klik in Solution Explorer met de rechtermuisknop op het project superfastcode2 en selecteer Eigenschappen.
Selecteer Release boven aan het dialoogvenster Eigenschappenpagina's voor het veld Configuratie. (Mogelijk ziet u deze optie met het actieve voorvoegsel.)
Vouw in het dialoogvenster op het tabblad C/C++>Algemeen de vervolgkeuzelijst voor de eigenschap Extra mappen opnemen uit en selecteer Bewerken.
Voeg in het pop-upvenster de lijst met gekopieerde paden toe:
Herhaal deze stappen voor elk pad in de samengevoegde lijst die u hebt gekopieerd uit het Venster Developer PowerShell :
Selecteer Nieuwe lijn (map met plussymbool) op de werkbalk van het pop-up-venster.
Visual Studio voegt boven aan de lijst met paden een lege regel toe en plaatst de cursor aan het begin.
Plak het pad PyBind11 in de lege regel.
U kunt ook Meer opties (...) selecteren en een pop-upvenster van verkenner gebruiken om naar de padlocatie te bladeren.
Belangrijk
- Als het pad het
-I
voorvoegsel bevat, verwijdert u het voorvoegsel uit het pad. - Opdat Visual Studio een pad herkent, moet het pad op een afzonderlijke regel staan.
Nadat u een nieuw pad hebt toegevoegd, wordt in Visual Studio het bevestigd pad weergegeven in het veld Geëvalueerde waarde .
- Als het pad het
Selecteer OK om het pop-upvenster af te sluiten.
Beweeg boven in het dialoogvenster Eigenschappenpagina's de muisaanwijzer over de waarde voor de eigenschap Extra inclusief mappen en controleer of de PyBind11-paden aanwezig zijn.
Selecteer OK om de eigenschapswijzigingen toe te passen.
Het module.cpp-bestand bijwerken
De laatste stap bestaat uit het toevoegen van het pyBind11-headerbestand en de macrocode aan het project C++-bestand.
Open het module.cpp-bestand in de code-editor voor het superfastcode2 C++-project.
Voeg boven aan het module.cpp-bestand een instructie toe om het headerbestand pybind11.h op te nemen:
#include <pybind11/pybind11.h>
Voeg aan het einde van het module.cpp-bestand code toe voor de
PYBIND11_MODULE
macro om het toegangspunt voor de C++-functie te definiëren:namespace py = pybind11; PYBIND11_MODULE(superfastcode2, m) { m.def("fast_tanh2", &tanh_impl, R"pbdoc( Compute a hyperbolic tangent of a single argument expressed in radians. )pbdoc"); #ifdef VERSION_INFO m.attr("__version__") = VERSION_INFO; #else m.attr("__version__") = "dev"; #endif }
Bouw het C++-project en verifieer uw code. Als er fouten optreden, raadpleegt u de volgende sectie, Compileerfouten oplossen.
Compileerfouten oplossen
Bekijk de volgende secties voor mogelijke problemen waardoor de C++-modulebuild mislukt.
Fout: kan headerbestand niet vinden
Visual Studio retourneert een foutbericht zoals E1696: Kan het bronbestand Python.h of C1083 niet openen: Bestand kan niet worden geopend: 'Python.h': Geen dergelijk bestand of map.
Deze fout geeft aan dat de compiler geen vereist headerbestand (.h) voor uw project kan vinden.
Voor het project superfastcode controleert u of de projecteigenschap C/C++>Algemeen>Aanvullende Insluitdirectory's het pad naar de inclusiemap voor uw Python-installatie bevat. Bekijk de stappen in Projecteigenschappen configureren.
Controleer voor het superfastcode2-project of dezelfde projecteigenschap het pad naar de insluitingsmap voor de installatie van PyBind11 bevat. Bekijk de stappen voeg PyBind-paden toe aan het project.
Zie de Python-documentatie voor meer informatie over toegang tot de configuratiegegevens van uw Python-installatie.
Fout: Kan Python-bibliotheken niet vinden
Visual Studio retourneert een fout die aangeeft dat de compiler de vereiste bibliotheekbestanden (DLL)-bestanden voor uw project niet kan vinden.
- Controleer voor het C++-project (superfastcode of superfastcode2) of de eigenschap Linker>General>Additional Library Directories het pad naar de map bibliotheken voor uw Python-installatie bevat. Bekijk de stappen in Projecteigenschappen configureren.
Zie de Python-documentatie voor meer informatie over toegang tot de configuratiegegevens van uw Python-installatie.
Linkerfouten met betrekking tot doelarchitectuur
Visual Studio rapporteert linkerfouten met betrekking tot de configuratie van de doelarchitectuur voor uw project, zoals x64 of Win32.
- Voor het C++-project (superfastcode of superfastcode2) wijzigt u de doelconfiguratie zodat deze overeenkomt met uw Python-installatie. Als de C++-projectdoelconfiguratie bijvoorbeeld Win32 is, maar uw Python-installatie 64-bits is, wijzigt u de C++-projectdoelconfiguratie in x64.
De code testen en de resultaten vergelijken
Nu u de DLL's hebt gestructureerd als Python-extensies, kunt u ernaar verwijzen vanuit het Python-project, de modules importeren en hun methoden gebruiken.
Uw DLL beschikbaar maken voor Python
U kunt uw DLL op verschillende manieren beschikbaar maken voor Python. Hier volgen twee opties om rekening mee te houden:
Als uw Python-project en C++-project zich in dezelfde oplossing bevinden, kunt u de volgende methode gebruiken:
Klik in Solution Explorer met de rechtermuisknop op het knooppunt Verwijzingen in uw Python-project en selecteer Verwijzing toevoegen.
Zorg ervoor dat u deze actie uitvoert voor uw Python-project en niet voor uw C++-project.
Vouw in het dialoogvenster Verwijzing toevoegen het tabblad Projecten uit.
Schakel de selectievakjes in voor zowel de superfastcode - als de superfastcode2-projecten en selecteer OK.
Een alternatieve methode is het installeren van de C++-extensiemodule in uw Python-omgeving. Met deze methode maakt u de module beschikbaar voor andere Python-projecten. Zie de documentatie van het setuptools-project voor meer informatie.
Voer de volgende stappen uit om de C++-extensiemodule in uw Python-omgeving te installeren:
Klik in Solution Explorer met de rechtermuisknop op uw C++-project en selecteerNieuw item>.
Selecteer C++-bestand (.cpp) in de lijst met bestandssjablonen.
Voer de naam voor het bestand in als setup.py en selecteer vervolgens Toevoegen.
Zorg ervoor dat u de bestandsnaam invoert met de Python-extensie (.py). Visual Studio herkent het bestand als Python-code ondanks het gebruik van de C++-bestandssjabloon.
Visual Studio opent het nieuwe bestand in de code-editor.
Plak de volgende code in het nieuwe bestand. Kies de codeversie die overeenkomt met uw extensiemethode:
CPython-extensies (superfastcode-project ):
from setuptools import setup, Extension sfc_module = Extension('superfastcode', sources = ['module.cpp']) setup( name='superfastcode', version='1.0', description='Python Package with superfastcode C++ extension', ext_modules=[sfc_module] )
PyBind11 (project superfastcode2 ):
from setuptools import setup, Extension import pybind11 cpp_args = ['-std=c++11', '-stdlib=libc++', '-mmacosx-version-min=10.7'] sfc_module = Extension( 'superfastcode2', sources=['module.cpp'], include_dirs=[pybind11.get_include()], language='c++', extra_compile_args=cpp_args, ) setup( name='superfastcode2', version='1.0', description='Python package with superfastcode2 C++ extension (PyBind11)', ext_modules=[sfc_module], )
Maak in het C++-project een tweede bestand met de naam pyproject.toml en plak de volgende code:
[build-system] requires = ["setuptools", "wheel", "pybind11"] build-backend = "setuptools.build_meta"
Het TOML-bestand (.toml) maakt gebruik van de Tom's Obvious, Minimal Language-indeling voor configuratiebestanden.
Als u de extensie wilt maken, klikt u met de rechtermuisknop op de bestandsnaam pyproject.toml op het tabblad codevenster en selecteert u Volledig pad kopiëren.
U verwijdert de naam pyproject.toml uit het pad voordat u deze gebruikt.
Vouw in Solution Explorer het knooppunt Python-omgevingen voor de oplossing uit.
Klik met de rechtermuisknop op de actieve Python-omgeving (vetgedrukt weergegeven) en selecteer Python-pakketten beheren.
Het deelvenster Python-omgevingen wordt geopend.
Als het benodigde pakket al is geïnstalleerd, ziet u het in dit deelvenster.
- Voordat u doorgaat, selecteert u de X naast de pakketnaam om deze te verwijderen.
Plak in het zoekvak voor het deelvenster Python-omgevingen het gekopieerde pad en verwijder de bestandsnaam pyproject.toml vanaf het einde van het pad.
Selecteer Enter om de module te installeren vanaf de locatie van het gekopieerde pad.
Aanbeveling
Als de installatie mislukt vanwege een machtigingsfout, voegt u het
--user
argument toe aan het einde van de opdracht en probeert u de installatie opnieuw uit te voeren.
De DLL aanroepen vanuit Python
Nadat u het DLL-bestand beschikbaar hebt gesteld voor Python, zoals beschreven in de vorige sectie, kunt u de superfastcode.fast_tanh
en superfastcode2.fast_tanh2
functies aanroepen vanuit Python. Vervolgens kunt u de functieprestaties vergelijken met de Python-implementatie.
Volg deze stappen om de DLL van de extensiemodule aan te roepen vanuit Python:
Open het .py-bestand voor uw Python-project in de code-editor.
Voeg aan het einde van het bestand de volgende code toe om de methoden aan te roepen die zijn geëxporteerd uit de DLL's en hun uitvoer weer te geven:
from superfastcode import fast_tanh test(lambda d: [fast_tanh(x) for x in d], '[fast_tanh(x) for x in d] (CPython C++ extension)') from superfastcode2 import fast_tanh2 test(lambda d: [fast_tanh2(x) for x in d], '[fast_tanh2(x) for x in d] (PyBind11 C++ extension)')
Voer het Python-programma uit door Foutopsporing>starten zonder foutopsporing te selecteren of gebruik de sneltoets Ctrl+F5.
Opmerking
Als de opdracht Starten zonder foutopsporing niet beschikbaar is, klikt u in Solution Explorer met de rechtermuisknop op het Python-project en selecteert u Instellen als opstartproject.
Wanneer het programma wordt uitgevoerd, ziet u dat de C++-routines ongeveer 5 tot 20 keer sneller worden uitgevoerd dan de Python-implementatie.
Hier volgt een voorbeeld van typische programma-uitvoer:
Running benchmarks with COUNT = 500000 [tanh(x) for x in d] (Python implementation) took 0.758 seconds [fast_tanh(x) for x in d] (CPython C++ extension) took 0.076 seconds [fast_tanh2(x) for x in d] (PyBind11 C++ extension) took 0.204 seconds
Probeer de
COUNT
variabele te verhogen, zodat de tijdverschillen duidelijker zijn.Een foutopsporingsbuild van de C++-module wordt ook langzamer uitgevoerd dan een release-build omdat de foutopsporingsbuild minder is geoptimaliseerd en verschillende foutcontroles bevat. Probeer te schakelen tussen de buildconfiguraties voor vergelijking, maar vergeet niet om de eigenschappen bij te werken die u eerder hebt ingesteld voor de releaseconfiguratie.
Snelheid en overhead van het proces oplossen
In de uitvoer ziet u mogelijk dat de PyBind11-extensie niet zo snel is als de CPython-extensie, hoewel deze sneller moet zijn dan de pure Python-implementatie. De belangrijkste reden voor het verschil is vanwege het gebruik van de METH_O vlag. Deze vlag biedt geen ondersteuning voor meerdere parameters, parameternamen of trefwoordargumenten. PyBind11 genereert iets complexere code om een meer Python-achtige interface te bieden aan bellers. Omdat de testcode de functie 500.000 keer aanroept, kunnen de resultaten de overhead aanzienlijk vergroten.
U kunt de overhead verder verminderen door de for
lus naar de systeemeigen Python-code te verplaatsen. Deze benadering omvat het gebruik van het iterator-protocol (of het type PyBind11 py::iterable
voor de functieparameter) om elk element te verwerken. Het verwijderen van de herhaalde overgangen tussen Python en C++ is een effectieve manier om de tijd te verkorten die nodig is om de reeks te verwerken.
Importfouten oplossen
Als u een ImportError
bericht ontvangt wanneer u uw module probeert te importeren, kunt u deze op een van de volgende manieren oplossen:
Wanneer u een project bouwt via een projectreferentie, zorg ervoor dat uw C++-eigenschappen overeenkomen met de geactiveerde Python-omgeving voor uw Python-project. Controleer of dezelfde maplocaties worden gebruikt voor de bestandsindelingen Include (.h) en Library (DLL).
Zorg ervoor dat uw uitvoerbestand de juiste naam heeft, zoals superfastcode.pyd. Een onjuiste naam of extensie voorkomt het importeren van het benodigde bestand.
Als u de module installeert met behulp van het setup.py-bestand , moet u de
pip
opdracht uitvoeren in de Python-omgeving die is geactiveerd voor uw Python-project. Wanneer u de actieve Python-omgeving voor uw project uitvouwt in Solution Explorer, ziet u een vermelding voor het C++-project, zoals superfaste code.
Fouten opsporen in C++-code
Visual Studio biedt ondersteuning voor foutopsporing van Python- en C++-code. De volgende stappen laten het foutopsporingsproces voor het superfastcode C++-project zien, maar het proces is hetzelfde voor het superfastcode2-project .
Klik in Solution Explorer met de rechtermuisknop op het Python-project en selecteer Eigenschappen.
Selecteer in het deelvenster Eigenschappen het tabblad Foutopsporing en selecteer vervolgens de> optieSysteemeigen codeopsporing inschakelen.
Aanbeveling
Wanneer u systeemeigen codeopsporing inschakelt, wordt het Python-uitvoervenster mogelijk onmiddellijk gesloten nadat het programma is voltooid, zonder te pauzeren en de Druk op een willekeurige toets om door te gaan prompt weer te geven. Als u de pauze en prompt wilt afdwingen nadat u native code debugging hebt ingeschakeld, voegt u het
-i
argument toe aan het veld Argumenten voor uitvoeren>interpreter op het tabblad Foutopsporing. Met dit argument zet u de Python-interpreter in de interactieve modus nadat de code is uitgevoerd. Het programma wacht totdat u Ctrl+Z+Enter- selecteert om het venster te sluiten. Een alternatieve benadering is het toevoegen vanimport os
- enos.system("pause")
-instructies aan het einde van uw Python-programma. Met deze code wordt de oorspronkelijke pauzeprompt gedupliceerd.Selecteer Bestand>opslaan (of Ctrl+S) om de eigenschapswijzigingen op te slaan.
Stel op de werkbalk van Visual Studio de Buildconfiguratie in op Debug.
Omdat code over het algemeen langer duurt om te worden uitgevoerd in het foutopsporingsprogramma, kunt u de
COUNT
variabele in uw Python-project .py bestand wijzigen in een waarde die ongeveer vijf keer kleiner is dan de standaardwaarde. Wijzig deze bijvoorbeeld van 5000000 in100000.Stel in uw C++-code een onderbrekingspunt in op de eerste regel van de
tanh_impl
methode.Start het foutopsporingsprogramma door Foutopsporing> starten te selecteren of gebruik de sneltoets F5.
Het foutopsporingsprogramma stopt wanneer de onderbrekingspuntcode wordt aangeroepen. Als het onderbrekingspunt niet wordt bereikt, controleert u of de configuratie is ingesteld op Foutopsporing en of u het project hebt opgeslagen. Dit gebeurt niet automatisch wanneer u het foutopsporingsprogramma start.
Op het onderbrekingspunt kunt u de C++-code doorlopen, variabelen onderzoeken, enzovoort. Zie Debug Python en C++ samen voor meer informatie over deze functies.
Alternatieve benaderingen
U kunt Python-extensies op verschillende manieren maken, zoals beschreven in de volgende tabel. De eerste twee rijen CPython
en PyBind11
, worden in dit artikel besproken.
Methode | Wijnoogst | Representatieve gebruikers |
---|---|---|
C/C++-extensiemodules voor CPython |
1991 | Standaardbibliotheek |
PyBind11 (aanbevolen voor C++) | 2015 | |
Cython (aanbevolen voor C) | 2007 | gevent, kivy |
HPy | 2019 | |
mypyc | 2017 | |
ctypes | 2003 | oscrypto |
cffiffi | 2013 | cryptografie, pypy |
ZUIPEN | 1996 | crfsuite |
Boost.Python | 2002 | |
cppyy | 2017 |