Vytvoření rozšíření jazyka C++ pro Python v sadě Visual Studio

V tomto článku vytvoříte modul rozšíření C++ pro CPython pro výpočet hyperbolického tangensu a zavoláte ho z kódu Pythonu. Rutina se implementuje jako první v Pythonu, aby ukázala relativní výkon implementace stejné rutiny v jazyce C++.

Moduly kódu napsané v jazyce C++ (nebo C) se běžně používají k rozšíření možností interpreta Pythonu. Existují tři primární typy rozšiřujících modulů:

  • Moduly akcelerátoru: Povolte akcelerovaný výkon. Vzhledem k tomu, že Python je interpretovaný jazyk, můžete v jazyce C++ napsat modul akcelerátoru pro zajištění vyššího výkonu.
  • Obálkové moduly: Zveřejnění existujících rozhraní C/C++ pro kód Pythonu nebo zveřejnění rozhraní API podobné pythonu, které se dá snadno používat z Pythonu.
  • Moduly přístupu systému nízké úrovně: Vytvořte moduly pro přístup k systému, abyste dosáhli funkcí CPython modulu runtime nižší úrovně, operačního systému nebo základního hardwaru.

Tento článek ukazuje dva způsoby, jak zpřístupnit modul rozšíření jazyka C++pro Python:

  • Použijte standardní CPython rozšíření, jak je popsáno v dokumentaci k Pythonu.
  • Použijte PyBind11, který doporučujeme pro C++11 kvůli jednoduchosti. Pokud chcete zajistit kompatibilitu, ujistěte se, že pracujete s jednou z novějších verzí Pythonu.

Dokončená ukázka pro tento názorný postup je k dispozici na GitHubu na python-samples-vs-cpp-extension.

Požadavky

  • Visual Studio 2017 nebo novější s nainstalovanou úlohou vývoje v Pythonu Tato úloha zahrnuje nativní vývojové nástroje Pythonu, které přidávají sady funkcí a sad nástrojů C++, které jsou nezbytné pro nativní rozšíření.

    Screenshot of a list of Python development options, highlighting the Python native development tools option.

    Další informace o možnostech instalace najdete v tématu Instalace podpory Pythonu pro Visual Studio.

    Poznámka:

    Při instalaci úlohy datových věd a analytických aplikací se ve výchozím nastavení nainstalují Python a možnost nativních vývojových nástrojů Pythonu.

  • Pokud instalujete Python samostatně, nezapomeňte v instalačním programu Pythonu vybrat možnost Stáhnout symboly ladění v části Upřesnit možnosti . Tato možnost je nutná pro použití ladění ve smíšeném režimu mezi kódem Pythonu a nativním kódem.

Vytvoření aplikace v Pythonu

Pomocí těchto kroků vytvořte aplikaci v Pythonu.

  1. V sadě Visual Studio vytvořte nový projekt Pythonu tak, že vyberete Soubor>nový>projekt.

  2. V dialogovém okně Vytvořit nový projekt vyhledejte Python. Vyberte šablonu aplikace Pythonu a vyberte Další.

  3. Zadejte název a umístění projektu a vyberte Vytvořit.

    Visual Studio vytvoří nový projekt. Projekt se otevře v Průzkumník řešení a soubor projektu (.py) se otevře v editoru kódu.

  4. Do souboru .py vložte následující kód. Pokud chcete vyzkoušet některé funkce pro úpravy Pythonu, zkuste kód zadat ručně.

    Tento kód vypočítá hyperbolický tangens bez použití matematické knihovny a později to urychlíte pomocí nativních rozšíření Pythonu.

    Tip

    Než ho přepíšete v jazyce C++, napíšete svůj kód v čistém Pythonu. Tímto způsobem můžete snadněji zkontrolovat, jestli je váš nativní kód Pythonu správný.

    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)')
    
  5. Spusťte program tak, že vyberete Spustit ladění>bez ladění nebo vyberete klávesovou zkratku Ctrl+F5.

    Otevře se příkazové okno pro zobrazení výstupu programu.

  6. Ve výstupu si všimněte množství času hlášeného pro proces srovnávacího testu.

    V tomto názorném postupu by měl proces srovnávacího testu trvat přibližně 2 sekundy.

  7. Podle potřeby upravte hodnotu COUNT proměnné v kódu, aby se srovnávací test dokončil přibližně za 2 sekundy na vašem počítači.

  8. Spusťte program znovu a potvrďte, že upravená COUNT hodnota vytvoří srovnávací test přibližně za 2 sekundy.

Tip

Při spouštění srovnávacích testů vždy používejte možnost Spustit ladění>bez možnosti Ladění. Tato metoda pomáhá vyhnout se režii, která se může zobrazit při spuštění kódu v ladicím programu sady Visual Studio.

Vytvoření základních projektů C++

Pomocí těchto kroků vytvořte dva identické projekty C++, superfastcode a superfastcode2. Později v každém projektu použijete jiný přístup k zveřejnění kódu C++ v Pythonu.

  1. V Průzkumník řešení klikněte pravým tlačítkem na název řešení a vyberte Přidat>nový projekt.

    Řešení sady Visual Studio může obsahovat projekty Pythonu i C++, což je jednou z výhod použití sady Visual Studio pro vývoj v Pythonu.

  2. V dialogovém okně Přidat nový projekt nastavte filtr jazyka na C++ a do vyhledávacího pole zadejte prázdné.

  3. V seznamu výsledků šablony projektu vyberte Prázdný projekt a vyberte Další.

  4. V dialogovém okně Konfigurovat nový projekt zadejte název projektu:

    • Pro první projekt zadejte název superfastcode.
    • Pro druhý projekt zadejte název superfastcode2.
  5. Vyberte Vytvořit.

Nezapomeňte tyto kroky zopakovat a vytvořit dva projekty.

Tip

Alternativní přístup je k dispozici, pokud máte v sadě Visual Studio nainstalované nativní vývojové nástroje Pythonu. Můžete začít se šablonou modulu rozšíření Pythonu, která předem dokončí mnoho kroků popsaných v tomto článku.

Návod v tomto článku vám pomůže začít s prázdným projektem, který vám pomůže krok za krokem sestavit modul rozšíření. Po pochopení procesu můžete pomocí alternativní šablony ušetřit čas při psaní vlastních rozšíření.

Přidání souboru C++ do projektu

V dalším kroku přidejte do každého projektu soubor C++.

  1. V Průzkumník řešení rozbalte projekt, klikněte pravým tlačítkem myši na uzel Zdrojové soubory a vyberte Přidat>novou položku.

  2. V seznamu šablon souborů vyberte soubor C++ (.cpp).

  3. Jako module.cpp zadejte název souboru a pak vyberte Přidat.

    Důležité

    Ujistěte se, že název souboru obsahuje příponu .cpp . Visual Studio hledá soubor s příponou .cpp , aby bylo možné zobrazit stránky vlastností projektu C++.

  4. Na panelu nástrojů rozbalte rozevírací nabídku Konfigurace a vyberte typ konfigurace cíle:

    Screenshot that shows how to set the target configuration type for the C++ project in Visual Studio.

    • V případě 64bitového modulu runtime Pythonu aktivujte konfiguraci x64 .
    • V případě 32bitového modulu runtime Pythonu aktivujte konfiguraci Win32 .

Nezapomeňte tyto kroky zopakovat pro oba projekty.

Konfigurace vlastností projektu

Před přidáním kódu do nových souborů C++ nakonfigurujte vlastnosti pro každý projekt modulu C++ a otestujte konfigurace, abyste měli jistotu, že všechno funguje.

Potřebujete nastavit vlastnosti projektu pro konfigurace sestavení ladění i vydané verze každého modulu.

  1. V Průzkumník řešení klikněte pravým tlačítkem myši na projekt modulu C++ (superfastcode nebo superfastcode2) a vyberte Vlastnosti.

  2. Nakonfigurujte vlastnosti pro sestavení ladění modulu a pak nakonfigurujte stejné vlastnosti pro sestavení vydané verze :

    V horní části dialogového okna Stránky vlastností projektu nakonfigurujte následující možnosti konfigurace souboru:

    Screenshot that shows how to set the project build and platform options for the C++ file in Visual Studio.

    1. V části Konfigurace vyberte Ladit nebo Uvolnit. (Tyto možnosti se můžou zobrazit pomocí Aktivní předpona.)

    2. Pro platformu vyberte v závislosti na výběru v předchozím kroku aktivní (x64) nebo Aktivní (Win32).

      Poznámka:

      Při vytváření vlastních projektů budete chtít nakonfigurovat konfigurace ladění a vydávání samostatně podle konkrétních požadavků na scénář. V tomto cvičení nastavíte konfigurace tak, aby používaly build verze CPythonu. Tato konfigurace zakáže některé funkce ladění modulu runtime C++, včetně kontrolních výrazů. Použití binárních souborů ladění CPython (python_d.exe) vyžaduje různá nastavení.

    3. Nastavte další vlastnosti projektu, jak je popsáno v následující tabulce.

      Pokud chcete změnit hodnotu vlastnosti, zadejte hodnotu do pole vlastnosti. U některých polí můžete vybrat aktuální hodnotu a rozbalit rozevírací nabídku voleb nebo otevřít dialogové okno, které vám pomůže definovat hodnotu.

      Po aktualizaci hodnot na kartě vyberte Před přepnutím na jinou kartu možnost Použít . Tato akce pomáhá zajistit, aby vaše změny zůstaly.

      Tab a section Vlastnost Hodnota
      Obecné vlastnosti>konfigurace Název cíle Zadejte název modulu, který se na něj má odkazovat z Pythonu v from...import příkazech, jako je superfastcode. Stejný název použijete v kódu C++ při definování modulu pro Python. Pokud chcete jako název modulu použít název projektu, ponechte výchozí hodnotu $<ProjectName>. Pokud python_d.exechcete, přidejte _d na konec názvu.
      Typ konfigurace Dynamická knihovna (.dll)
      Upřesnit vlastnosti>konfigurace Cílová přípona souboru .pyd (modul rozšíření Pythonu)
      Obecné C/C++> Další adresáře zahrnutí Podle potřeby přidejte složku pro zahrnutí Pythonu (například c:\Python36\include).
      Preprocesor C/C++> Definice preprocesoru Pokud je k dispozici, změňte hodnotu _DEBUG na NDEBUG tak, aby odpovídala nedebugové verzi CPythonu. Pokud použijete python_d.exe, ponechte tuto hodnotu beze změny.
      Generování kódu C/C++> Knihovna modulu runtime Knihovna DLL s více vlákny (/MD) tak , aby odpovídala verzi CPythonu (nedebug). Pokud použijete python_d.exe, ponechte tuto hodnotu jako knihovnu DLL s více vlákny (/MDd).
      Základní kontroly modulu runtime Výchozí
      Obecné linkery> Další adresáře knihovny Přidejte složku knihovny Pythonu, která obsahuje soubory .lib, podle potřeby pro instalaci (například c:\Python36\libs). Nezapomeňte odkazovat na složku knihovny , která obsahuje soubory .lib , a ne složku Lib , která obsahuje .py soubory.

      Důležité

      Pokud karta C/C++ není zobrazena jako možnost vlastností projektu, pak projekt neobsahuje žádné soubory kódu, které Sada Visual Studio identifikuje jako zdrojové soubory C/C++. K této podmínce může dojít, pokud vytvoříte zdrojový soubor bez přípony souboru .c nebo .cpp .

      Pokud jste omylem zadali module.coo místo module.cpp při vytváření souboru C++, Visual Studio vytvoří soubor, ale nenastaví typ souboru na kompilátor C/C+. Tento typ souboru je nezbytný k aktivaci přítomnosti karty vlastností C/C++ v dialogovém okně vlastností projektu. Chybné identifikace zůstane i v případě, že přejmenujete soubor kódu s příponou .cpp .

      Chcete-li správně nastavit typ souboru kódu, klikněte v Průzkumník řešení pravým tlačítkem myši na soubor kódu a vyberte Vlastnosti. Jako typ položky vyberte kompilátor C/C++.

    4. Po aktualizaci všech vlastností vyberte OK.

    Opakujte kroky pro jinou konfiguraci sestavení.

  3. Otestujte aktuální konfiguraci. Opakujte následující kroky pro sestavení ladění i vydané verze obou projektů C++.

    1. Na panelu nástrojů sady Visual Studio nastavte konfiguraci sestavení na Ladění nebo vydání:

      Screenshot that shows how to set the build configuration for the C++ project in Visual Studio.

    2. V Průzkumník řešení klikněte pravým tlačítkem myši na projekt C++ a vyberte Sestavit.

      Soubory .pyd jsou ve složce řešení , v části Debug and Release, a ne v samotné složce projektu C++.

Přidání kódu a testovací konfigurace

Teď jste připraveni přidat kód do souborů C++ a otestovat sestavení vydané verze .

  1. Pro projekt C++ superfastcode otevřete soubor module.cpp v editoru kódu.

  2. Do souboru module.cpp vložte následující kód:

    #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);
    }
    
  3. Uložte provedené změny.

  4. Sestavte konfiguraci verze pro projekt C++, abyste potvrdili správnost kódu.

Opakujte kroky pro přidání kódu do souboru C++ pro projekt superfastcode2 a otestujte sestavení vydané verze.

Převod projektů C++ na rozšíření Pythonu

Chcete-li knihovnu DLL jazyka C++ nastavit jako rozšíření pro Python, nejprve upravíte exportované metody pro interakci s typy Pythonu. Pak přidejte funkci pro export modulu spolu s definicemi metod modulu.

Následující části ukazují, jak vytvořit rozšíření pomocí rozšíření CPython a PyBind11. Projekt superfasctcode používá rozšíření CPython a projekt superfasctcode2 implementuje PyBind11.

Použití rozšíření CPython

Další informace o kódu zobrazeném v této části najdete v referenční příručce k rozhraní PYTHON/C API, zejména na stránce Objekty modulu. Při kontrole referenčního obsahu nezapomeňte v rozevíracím seznamu v pravém horním rohu vybrat svou verzi Pythonu.

  1. Pro projekt C++ superfastcode otevřete soubor module.cpp v editoru kódu.

  2. Na začátek souboru module.cpp přidejte příkaz, který bude obsahovat hlavičkový soubor Python.h :

    #include <Python.h>
    
  3. tanh_impl Nahraďte kód metody pro přijetí a vrácení typů Pythonu (to znamená :PyObject*

    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);
    }
    
  4. Na konec souboru přidejte strukturu, která definuje, jak prezentovat funkci C++ tanh_impl , do Pythonu:

    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 }
    };
    
  5. Přidejte další strukturu, která definuje, jak odkazovat na modul v kódu Pythonu, konkrétně při použití příkazu from...import .

    Název importovaný v tomto kódu by se měl shodovat s hodnotou ve vlastnostech projektu v části Obecné>název cíle vlastností>konfigurace.

    V následujícím příkladu "superfastcode" název znamená, že můžete použít from superfastcode import fast_tanh příkaz v Pythonu, protože fast_tanh je definován v rámci superfastcode_methods. Názvy souborů, které jsou interní pro projekt C++, například module.cpp, jsou nekonvenční.

    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
    };
    
  6. Přidejte metodu, kterou Python volá při načítání modulu. Název metody musí být PyInit_<module-name>, kde <název> modulu přesně odpovídá vlastnosti konfigurace>projektu C++ Obecné>cílové název. To znamená, že název metody odpovídá názvu souboru .pyd vytvořeného projektem.

    PyMODINIT_FUNC PyInit_superfastcode() {
        return PyModule_Create(&superfastcode_module);
    }
    
  7. Sestavte projekt C++ a ověřte kód. Pokud narazíte na chyby, přečtěte si část Řešení chyb kompilace.

Použití PyBind11

Pokud dokončíte kroky v předchozí části projektu superfastcode , můžete si všimnout, že cvičení vyžaduje často používaný kód k vytvoření struktur modulů pro rozšíření C++ CPython. V tomto cvičení zjistíte, že PyBind11 zjednodušuje proces kódování. Makra v souboru hlaviček jazyka C++ slouží k dosažení stejného výsledku, ale s mnohem menším kódem. K zajištění toho, aby Visual Studio mohl vyhledat knihovny PyBind11 a zahrnout soubory, je potřeba provést další kroky. Další informace o kódu v této části najdete v tématu Základy PyBind11.

Instalace PyBind11

Prvním krokem je instalace PyBind11 v konfiguraci projektu. V tomto cvičení použijete okno Developer PowerShellu .

  1. Otevřete okno PowerShellu pro vývojáře příkazového řádku>Nástroje.>

  2. V okně Developer PowerShell nainstalujte PyBind11 pomocí příkazu pip install pybind11 pip nebo py -m pip install pybind11.

    Visual Studio nainstaluje PyBind11 a závislé balíčky.

Přidání cest PyBind11 do projektu

Po instalaci PyBind11 musíte přidat cesty PyBind11 do vlastnosti Další adresáře include pro projekt.

  1. V Prostředí Developer PowerShell v okně spusťte příkaz python -m pybind11 --includes nebo py -m pybind11 --includes.

    Tato akce vytiskne seznam cest PyBind11, které potřebujete přidat do vlastností projektu.

  2. Zvýrazněte seznam cest v okně a na panelu nástrojů okna vyberte Kopírovat (dvojitá stránka).

    Screenshot that shows how to highlight and copy the list of paths from the Developer PowerShell window in Visual Studio.

    Seznam zřetězených cest se přidá do schránky.

  3. V Průzkumník řešení klikněte pravým tlačítkem myši na projekt superfastcode2 a vyberte Vlastnosti.

  4. V horní části dialogového okna Stránky vlastností vyberte pro pole Konfigurace možnost Uvolnit. (Tato možnost se může zobrazit pomocí Aktivní předpona.)

  5. V dialogovém okně na kartě C/C++>Obecné rozbalte rozevírací nabídku pro vlastnost Další adresáře include a vyberte Upravit.

  6. V místním dialogovém okně přidejte seznam zkopírovaných cest:

    Opakujte tento postup pro každou cestu v zřetězeného seznamu zkopírovaného z okna Developer PowerShellu:

    1. Na panelu nástrojů automaticky otevírané dialogové okno vyberte Nový řádek (složka se symbolem plus).

      Screenshot that shows how to add a PyBind11 path to the Additional Include Directories property.

      Visual Studio přidá prázdný řádek v horní části seznamu cest a umístí kurzor vložení na začátek.

    2. Vložte cestu PyBind11 do prázdného řádku.

      Můžete také vybrat Další možnosti (...) a pomocí automaticky otevírané dialogové okno Průzkumníka souborů přejít na umístění cesty.

      Důležité

      • Pokud cesta obsahuje předponu -I , odeberte ji z cesty.
      • Aby Visual Studio rozpoznal cestu, musí být cesta na samostatném řádku.

      Po přidání nové cesty se v sadě Visual Studio zobrazí potvrzená cesta v poli Vyhodnocená hodnota .

  7. Výběrem možnosti OK zavřete automaticky otevírané dialogové okno.

  8. V horní části dialogového okna Stránky vlastností najeďte myší na hodnotu vlastnosti Additional Include Directories a potvrďte, že jsou k dispozici cesty PyBind11.

  9. Chcete-li použít změny vlastností, vyberte OK .

Aktualizace souboru module.cpp

Posledním krokem je přidání souboru hlavičky PyBind11 a kódu makra do souboru C++ projektu.

  1. V případě projektu superfastcode2 C++ otevřete soubor module.cpp v editoru kódu.

  2. Na začátek souboru module.cpp přidejte příkaz, který bude obsahovat hlavičkový soubor pybind11.h :

    #include <pybind11/pybind11.h>
    
  3. Na konci souboru module.cpp přidejte kód makra, PYBIND11_MODULE který definuje vstupní bod funkce C++:

    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
    }
    
  4. Sestavte projekt C++ a ověřte kód. Pokud narazíte na chyby, přečtěte si další část Řešení chyb kompilace.

Řešení chyb kompilace

V následujících částech najdete možné problémy, které můžou způsobit selhání sestavení modulu C++.

Chyba: Nelze najít soubor hlaviček

Visual Studio vrátí chybovou zprávu typu E1696: Nejde otevřít zdrojový soubor Python.h nebo C1083: Nelze otevřít soubor: Python.h: Žádný takový soubor nebo adresář.

Tato chyba značí, že vyhoví tomuto požadavku nemůže najít požadovaný soubor hlavičky (.h) pro váš projekt.

  • V případě projektu superfastcode ověřte, že vlastnost projektu C/C++>General Additional>Include Directories obsahuje cestu ke složce include pro instalaci Pythonu. Projděte si kroky v části Konfigurace vlastností projektu.

  • V případě projektu superfastcode2 ověřte, že stejná vlastnost projektu obsahuje cestu ke složce include pro vaši instalaci PyBind11. Projděte si kroky ad PyBind cest k projektu.

Další informace o přístupu k informacím o konfiguraci instalace Pythonu najdete v dokumentaci k Pythonu.

Chyba: Nepodařilo se najít knihovny Pythonu

Visual Studio vrátí chybu, která značí, že vyhoví, nemůže najít požadované soubory knihovny (DLL) pro váš projekt.

  • Pro projekt C++ (superfastcode nebo superfastcode2) ověřte, zda vlastnost Linker>General>Additional Library Directories obsahuje cestu ke složce libs pro instalaci Pythonu. Projděte si kroky v části Konfigurace vlastností projektu.

Další informace o přístupu k informacím o konfiguraci instalace Pythonu najdete v dokumentaci k Pythonu.

Visual Studio hlásí chyby linkeru související s konfigurací cílové architektury pro váš projekt, například x64 nebo Win32.

  • U projektu C++ (superfastcode nebo superfastcode2) změňte cílovou konfiguraci tak, aby odpovídala instalaci Pythonu. Pokud je například konfigurace cíle projektu C++ Win32, ale instalace Pythonu je 64bitová, změňte konfiguraci cíle projektu C++ na x64.

Otestování kódu a porovnání výsledků

Teď, když máte knihovny DLL strukturované jako rozšíření Pythonu, můžete na ně odkazovat z projektu Pythonu, importovat moduly a používat jejich metody.

Zpřístupnění knihovny DLL pythonu

Knihovnu DLL můžete zpřístupnit pythonu několika způsoby. Tady jsou dvě možnosti, které je potřeba vzít v úvahu:

Pokud se projekt Pythonu a projekt C++ nacházejí ve stejném řešení, můžete použít následující přístup:

  1. V Průzkumník řešení klikněte pravým tlačítkem myši na uzel Reference v projektu Pythonu a vyberte Přidat odkaz.

    Nezapomeňte provést tuto akci pro projekt Pythonu, a ne pro projekt C++.

  2. V dialogovém okně Přidat odkaz rozbalte kartu Projekty .

  3. Zaškrtněte políčka u projektů superfastcode i superfastcode2 a vyberte OK.

    Screenshot that shows how to add a reference to the super fast code project in Visual Studio.

Alternativním přístupem je instalace modulu rozšíření C++ ve vašem prostředí Pythonu. Tato metoda zpřístupňuje modul ostatním projektům Pythonu. Další informace najdete v dokumentaci k projektu setuptools.

Provedením následujících kroků nainstalujte modul rozšíření C++ve vašem prostředí Pythonu:

  1. V Průzkumník řešení klikněte pravým tlačítkem na projekt C++ a vyberte Přidat>novou položku.

  2. V seznamu šablon souborů vyberte soubor C++ (.cpp).

  3. Jako setup.py zadejte název souboru a pak vyberte Přidat.

    Nezapomeňte zadat název souboru s příponou Python (.py). Visual Studio rozpozná soubor jako kód Pythonu navzdory použití šablony souboru C++.

    Visual Studio otevře nový soubor v editoru kódu.

  4. Do nového souboru vložte následující kód. Zvolte verzi kódu, která odpovídá vaší metodě rozšíření:

    • Rozšíření CPython (projekt superfastcode ):

      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 (projekt 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],
      )
      
  5. V projektu C++ vytvořte druhý soubor s názvem pyproject.toml a vložte následující kód:

    [build-system]
    requires = ["setuptools", "wheel", "pybind11"]
    build-backend = "setuptools.build_meta"
    

    Soubor TOML (.toml) používá pro konfigurační soubory formát Tom's Obvious, Minimal Language.

  6. Chcete-li vytvořit rozšíření, klikněte pravým tlačítkem myši na název souboru pyproject.toml na kartě okna kódu a vyberte Kopírovat úplnou cestu.

    Screenshot that shows how to copy the full path to the py project toml file in Visual Studio.

    Před použitím cesty odstraníte název pyproject.toml .

  7. V Průzkumník řešení rozbalte uzel Prostředí Pythonu pro řešení.

  8. Klikněte pravým tlačítkem na aktivní prostředí Pythonu (zobrazené tučně) a vyberte Spravovat balíčky Pythonu.

    Otevře se podokno Prostředí Pythonu.

    Pokud už je potřebný balíček nainstalovaný, zobrazí se v tomto podokně.

    • Než budete pokračovat, vyberte X vedle názvu balíčku a odinstalujte ho.

    Screenshot that shows how to uninstall a package in the Python Environments pane.

  9. Do vyhledávacího pole pro podokno Prostředí Pythonu vložte zkopírovanou cestu a odstraňte název souboru pyproject.toml z konce cesty.

    Screenshot that shows how to enter the path in the Python Environments pane to install the extension module.

  10. Výběrem klávesy Enter nainstalujte modul z umístění zkopírované cesty.

    Tip

    Pokud instalace selže kvůli chybě oprávnění, přidejte --user argument na konec příkazu a zkuste instalaci zopakovat.

Volání knihovny DLL z Pythonu

Po zpřístupnění knihovny DLL pro Python, jak je popsáno v předchozí části, jste připraveni volat superfastcode.fast_tanh funkce a superfastcode2.fast_tanh2 funkce z Pythonu. Pak můžete porovnat výkon funkce s implementací Pythonu.

Pokud chcete volat knihovnu DLL modulu rozšíření z Pythonu, postupujte takto:

  1. Otevřete soubor .py projektu Pythonu v editoru kódu.

  2. Na konec souboru přidejte následující kód pro volání metod exportovaných z knihoven DLL a zobrazení jejich výstupu:

    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)')
    
  3. Spusťte program Python tak, že vyberete Spustit ladění>bez ladění nebo použijete klávesovou zkratku Ctrl+F5.

    Poznámka:

    Pokud příkaz Spustit bez ladění není k dispozici, klikněte v Průzkumník řešení pravým tlačítkem myši na projekt Pythonu a pak vyberte Nastavit jako spouštěný projekt.

    Při spuštění programu si všimněte, že rutiny jazyka C++ běží přibližně 5 až 20krát rychleji než implementace Pythonu.

    Tady je příklad typického výstupu programu:

    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
    
  4. Zkuste proměnnou COUNT zvětšit, aby byly časové rozdíly výraznější.

    Sestavení ladění modulu C++ také běží pomaleji než sestavení vydané verze , protože sestavení ladění je méně optimalizované a obsahuje různé kontroly chyb. Zkuste přepnout mezi konfiguracemi sestavení pro porovnání, ale nezapomeňte aktualizovat vlastnosti, které jste nastavili dříve pro konfiguraci vydané verze.

Adresovat rychlost a režijní náklady na procesy

Ve výstupu si můžete všimnout, že rozšíření PyBind11 není tak rychlé jako rozšíření CPython, i když by mělo být rychlejší než čistá implementace Pythonu. Hlavním důvodem rozdílu je použití příznaku METH_O. Tento příznak nepodporuje více parametrů, názvů parametrů ani argumentů klíčových slov. PyBind11 vygeneruje trochu složitější kód, který volajícím poskytne více rozhraní podobné Pythonu. Vzhledem k tomu, že testovací kód volá funkci 500 000krát, výsledky mohou výrazně zvýšit režii.

Režijní náklady můžete dále snížit přesunutím for smyčky do nativního kódu Pythonu. Tento přístup zahrnuje použití protokolu iterátoru (nebo typu PyBind11 py::iterable pro parametr funkce) ke zpracování jednotlivých prvků. Odebrání opakovaných přechodů mezi Pythonem a C++ je efektivní způsob, jak zkrátit dobu potřebnou ke zpracování sekvence.

Řešení chyb importu

Pokud se vám při pokusu ImportError o import modulu zobrazí zpráva, můžete ji vyřešit jedním z následujících způsobů:

  • Při sestavování prostřednictvím odkazu na projekt se ujistěte, že vlastnosti projektu C++ odpovídají prostředí Pythonu aktivovanému pro váš projekt Pythonu. Ověřte, že se pro soubory Include (.h) a Library (DLL) používají stejná umístění složek.

  • Ujistěte se, že je výstupní soubor správně pojmenovaný, například superfastcode.pyd. Nesprávný název nebo přípona brání importu potřebného souboru.

  • Pokud modul nainstalujete pomocí souboru setup.py , nezapomeňte spustit pip příkaz v prostředí Python aktivovaném pro váš projekt Pythonu. Když v Průzkumník řešení rozbalíte aktivní prostředí Pythonu, měli byste vidět položku pro projekt C++, například superfastcode.

Ladění kódu C++

Visual Studio podporuje společně ladění kódu Pythonu a C++. Následující kroky ukazují proces ladění pro projekt superfastcode C++, ale proces je stejný pro projekt superfastcode2 .

  1. V Průzkumník řešení klikněte pravým tlačítkem na projekt Pythonu a vyberte Vlastnosti.

  2. V podokně Vlastnosti vyberte kartu Ladění a pak vyberte možnost Ladění>Povolit nativní ladění kódu.

    Tip

    Když povolíte ladění nativního kódu, okno výstupu Pythonu se může zavřít hned po dokončení programu bez pozastavení a zobrazení výzvy stisknutím libovolné klávesy . Chcete-li vynutit pozastavení a výzvu po povolení ladění nativního kódu, přidejte -i argument do pole Spustit>argumenty interpretu na kartě Ladění. Tento argument umístí interpret Pythonu do interaktivního režimu po spuštění kódu. Program čeká, až vyberete Ctrl+Z+Enter a zavřete okno. Alternativním přístupem je přidání import os příkazů os.system("pause") na konec programu v Pythonu. Tento kód duplikuje původní výzvu k pozastavení.

  3. Výběrem možnosti Uložit soubor>(nebo Ctrl+S) uložte změny vlastnosti.

  4. Na panelu nástrojů sady Visual Studio nastavte konfiguraci sestavení na Ladění.

  5. Vzhledem k tomu, že spuštění kódu v ladicím programu obvykle trvá déle, můžete COUNT změnit proměnnou v projektu Pythonu .py souboru na hodnotu, která je asi pětkrát menší než výchozí hodnota. Změňte ho například z 5 00000 na1 00000.

  6. V kódu C++ nastavte zarážku na prvním řádku tanh_impl metody.

  7. Ladicí program spusťte tak>, že vyberete Ladění spustit nebo použijete klávesovou zkratku F5.

    Ladicí program se zastaví při zavolání kódu zarážky. Pokud se zarážka nenarazí, zkontrolujte, jestli je konfigurace nastavená na Ladění a že jste projekt uložili, což se nestane automaticky při spuštění ladicího programu.

    Screenshot of C++ code that contains a breakpoint in Visual Studio.

  8. Na zarážce můžete procházet kód C++, zkoumat proměnné atd. Další informace o těchto funkcích najdete v tématu Ladění Pythonu a jazyka C++ společně.

Alternativní přístupy

Rozšíření Pythonu můžete vytvářet různými způsoby, jak je popsáno v následující tabulce. První dva řádky CPython a PyBind11, jsou popsány v tomto článku.

Přístup Starý Reprezentativní uživatelé
Moduly rozšíření C/C++ pro CPython 1991 Standardní knihovna
PyBind11 (doporučeno pro C++) 2015
Cython (doporučeno pro C) 2007 gevent, kivy
HPy 2019
mypyc 2017
ctypes 2003 oscrypto
cffi 2013 kryptografie, pypy
SWIG 1996 crfsuite
Boost.Python 2002
cppyy 2017