Python için C++ uzantısı oluşturmaCreate a C++ extension for Python

C++ (veya C) ile yazılan modüller genellikle bir Python yorumlayıcısının yeteneklerini genişletmek için ve alt düzey işletim sistemi özelliklerine erişimi etkinleştirmek için kullanılır.Modules written in C++ (or C) are commonly used to extend the capabilities of a Python interpreter as well as to enable access to low-level operating system capabilities. Üç tür modül birincil vardır:There are three primary types of modules:

  • Hızlandırıcı modülleri: Python, yorumlanan bir dil olduğundan, daha yüksek performans için belirli kod parçaları C++ dilinde yazılabilir.Accelerator modules: because Python is an interpreted language, certain pieces of code can be written in C++ for higher performance.
  • Sarmalayıcı modüller: mevcut C/C++ arabirimlerini Python kodu için kullanıma sunun veya Python 'dan kullanımı kolay bir "pythonic" API 'sini kullanıma sunun.Wrapper modules: expose existing C/C++ interfaces to Python code or expose a more "Pythonic" API that's easy to use from Python.
  • Düşük düzey sistem erişim modülleri: CPython çalışma zamanının, işletim sisteminin veya temel alınan donanımın alt düzey özelliklerine erişmek için oluşturulur.Low-level system access modules: created to access lower-level features of the CPython runtime, the operating system, or the underlying hardware.

Bu makalede, bir hiperbolik tanjantı hesaplayan ve Python kodundan çağıran Cpyıthon için bir C++ uzantı modülü oluşturma adımları anlatılmaktadır.This article walks through building a C++ extension module for CPython that computes a hyperbolic tangent and calls it from Python code. Bu yordam, C++ ' ta aynı yordamın uygulanması için göreli performans kazancı göstermek üzere Python 'da ilk olarak uygulanır.The routine is implemented first in Python to demonstrate the relative performance gain of implementing the same routine in C++.

Bu makale ayrıca, C++ ' ın Python için kullanılabilir hale getirme için iki yol gösterir:This article also demonstrates two ways to make the C++ available to Python:

Bu ve diğer yollardan bir karşılaştırma, bu makalenin sonundaki alternatif yaklaşımlar altında bulunur.A comparison between these and other means is found under alternative approaches at the end of this article.

Bu izlenecek yolda tamamlanan örnek Python-Samples-vs-cpp-Extension (GitHub) üzerinde bulunabilir.The completed sample from this walkthrough can be found on python-samples-vs-cpp-extension (GitHub).

ÖnkoşullarPrerequisites

  • Visual Studio 2017 veya üzeri, C++ Ile masaüstü geliştirme ve Python geliştirme iş yükleri için varsayılan seçeneklerle birlikte yüklenir.Visual Studio 2017 or later with both the Desktop Development with C++ and Python Development workloads installed with default options.

  • Python geliştirme iş yükünde, Python yerel geliştirme araçlarıiçin sağdaki kutuyu da seçin.In the Python Development workload, also select the box on the right for Python native development tools. Bu seçenek, bu makalede açıklanan yapılandırmanın çoğunu ayarlar.This option sets up most of the configuration described in this article. (Bu seçenek ayrıca C++ iş yükünü otomatik olarak içerir.)(This option also includes the C++ workload automatically.)

    Python yerel geliştirme araçları seçeneğini belirleme

    İpucu

    Veri bilimi ve analitik uygulamalar iş yükü yükleme, varsayılan olarak Python ve Python yerel geliştirme araçları seçeneğini de içerir.Installing the Data science and analytical applications workload also includes Python and the Python native development tools option by default.

Daha fazla bilgi için bkz. Visual Studio 'nun diğer sürümlerini kullanma dahil olmak üzere Visual Studio Için Python desteğini yüklemeyin.For more information, see Install Python support for Visual Studio, including using other versions of Visual Studio. Python 'u ayrı olarak yüklerseniz, hata ayıklama sembollerini indir ve yükleyicideki Gelişmiş Seçenekler altında hata ayıklama ikililerini indir ' i seçtiğinizden emin olun.If you install Python separately, be sure to select Download debugging symbols and Download debug binaries under Advanced Options in the installer. Bu seçenek, hata ayıklama derlemesi oluşturmayı seçerseniz gerekli hata ayıklama kitaplıklarının kullanılabilir olmasını sağlar.This option ensures that you have the necessary debug libraries available if you choose to do a debug build.

Python uygulaması oluşturmaCreate the Python application

  1. Dosya > Yeni > Proje' ye tıklayarak Visual Studio 'da yeni bir Python projesi oluşturun.Create a new Python project in Visual Studio by selecting File > New > Project. "Python" araması yapın, Python uygulama şablonunu seçin, uygun bir ad ve konum verin ve Tamam' ı seçin.Search for "Python", select the Python Application template, give it a suitable name and location, and select OK.

  2. C++ ile çalışma, 32 bitlik bir Python yorumlayıcısı kullanmanızı gerektirir (Python 3,6 veya üzeri önerilir).Working with C++ requires that you use a 32-bit Python interpreter (Python 3.6 or above recommended). Visual Studio 'nun Çözüm Gezgini penceresinde, proje düğümünü genişletin ve ardından Python ortamları düğümünü genişletin.In the Solution Explorer window of Visual Studio, expand the project node, then expand the Python Environments node. Varsayılan olarak 32 bitlik bir ortam görmüyorsanız (kalın veya genel varsayılanile etiketlenmiş), bir proje Için Python ortamı seçmekonusundaki yönergeleri izleyin.If you don't see a 32-bit environment as the default (either in bold, or labeled with global default), then follow the instructions on Select a Python environment for a project. 32 bit yorumlayıcı yüklü değilse bkz. Python yorumlayıcıları 'Nı yükleme.If you don't have a 32-bit interpreter installed, see Install Python interpreters.

  3. Projenin . Kopyala dosyasında, bir hiperbolik tanjantın (daha kolay karşılaştırma için matematik kitaplığı kullanılmadan uygulanır) hesaplamasını kıyaslandıran aşağıdaki kodu yapıştırın.In the project's .py file, paste the following code that benchmarks the computation of a hyperbolic tangent (implemented without using the math library for easier comparison). Python düzenlemesi özelliklerindenbazılarını denemek için kodu el ile girmeyi de ücretsiz olarak deneyin.Feel free to enter the code manually to experience some of the Python editing features.

    from itertools import islice
    from random import random
    from time import perf_counter
    
    COUNT = 500000  # Change this value depending on the speed of your computer
    DATA = list(islice(iter(lambda: (random() - 0.5) * 3.0, None), 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)')
    
  4. Sonuçları görmek için hata ayıklama > olmadan Başlat (CTRL + F5) komutunu kullanarak programı çalıştırın.Run the program using Debug > Start without Debugging (Ctrl+F5) to see the results. Bu COUNT değişkeni, kıyaslama süresini değiştirmek için ayarlayabilirsiniz.You can adjust the COUNT variable to change how long the benchmark takes to run. Bu izlenecek yolun amaçları doğrultusunda, sayımı iki saniye boyunca alacak şekilde ayarlayın.For the purposes of this walkthrough, set the count so that the benchmark take around two seconds.

İpucu

Kıyaslama çalıştırılırken, Debug > Visual Studio hata ayıklayıcısında kod çalıştırırken oluşan ek yükün oluşmasını önlemek için her zaman hata ayıklamaolmadan Başlat ' ı kullanın.When running benchmarks, always use Debug > Start without Debugging to avoid the overhead incurred when running code within the Visual Studio debugger.

Core C++ projelerini oluşturmaCreate the core C++ projects

"Superfastcode" ve "superfastcode2" adlı iki özdeş C++ projesi oluşturmak için bu bölümdeki yönergeleri izleyin.Follow the instructions in this section to create two identical C++ projects named "superfastcode" and "superfastcode2". Daha sonra, C++ kodunu Python 'da kullanıma sunmak için her bir projede farklı yollardan yararlanabilirsiniz.Later you'll use different means in each project to expose the C++ code to Python.

  1. PYTHONHOMEOrtam değişkeninin kullanmak Istediğiniz Python Yorumlayıcısına ayarlandığından emin olun.Make sure the PYTHONHOME environment variable is set to the Python interpreter you want to use. Visual Studio 'daki C++ projeleri, Python uzantısı oluştururken kullanılan Python. hgibi dosyaları bulmak için bu değişkene bağımlıdır.The C++ projects in Visual Studio rely on this variable to locate files such as python.h, which are used when creating a Python extension.

  2. Çözüm Gezgini çözüme sağ tıklayın ve Add > Yeni projeEkle ' yi seçin.Right-click the solution in Solution Explorer and select Add > New Project. Visual Studio çözümü, hem Python hem de C++ projelerini birlikte içerebilir (Python için Visual Studio kullanmanın avantajlarından biridir).A Visual Studio solution can contain both Python and C++ projects together (which is one of the advantages of using Visual Studio for Python).

  3. "C++" üzerinde arama yapın, boş proje' yi seçin, "superfastcode" (ikinci proje için "superfastcode2") adını belirtin ve Tamam' ı seçin.Search on "C++", select Empty project, specify the name "superfastcode" ("superfastcode2" for the second project), and select OK.

    İpucu

    Visual Studio 'da Python yerel geliştirme araçları sayesinde, bunun yerine, aşağıda açıklananlar daha fazla olan Python uzantı modülü şablonuyla başlayabilirsiniz.With the Python native development tools installed in Visual Studio, you can start with the Python Extension Module template instead, which has much of what's described below already in place. Bu kılavuzda, ancak boş bir projeden başlamak, uzantı modülünün adım adım şekilde oluşturulmasını gösterir.For this walkthrough, though, starting with an empty project demonstrates building the extension module step by step. İşlemi anladıktan sonra şablon, kendi uzantılarınızı yazarken size zaman kazandırır.Once you understand the process, the template saves you time when writing your own extensions.

  4. Yeni projede, kaynak dosyaları düğümüne sağ tıklayıp yeni öğe Ekle' yi seçin, > New Item C++ dosyası' nı seçin module.cpp ve ardından Tamam' ı seçin.Create a C++ file in the new project by right-clicking the Source Files node, then select Add > New Item, select C++ File, name it module.cpp, and select OK.

    Önemli

    . Cpp uzantısına sahip bir dosya, Izleyen adımlarda C++ Özellik sayfalarını açmak için gereklidir.A file with the .cpp extension is necessary to turn on the C++ property pages in the steps that follow.

  5. Çözüm Gezgini' de C++ projesine sağ tıklayın, Özellikler' i seçin.Right-click the C++ project in Solution Explorer, select Properties.

  6. Görüntülenen Özellik sayfaları iletişim kutusunun üst kısmında, yapılandırmayı tüm yapılandırmalar ve Platform için Win32olarak ayarlayın.At the top of the Property Pages dialog that appears, set Configuration to All Configurations and Platform to Win32.

  7. Aşağıdaki tabloda açıklandığı gibi belirli özellikleri ayarlayın ve ardından Tamam' ı seçin.Set the specific properties as described in the following table, then select OK.

    TabTab ÖzellikProperty DeğerValue
    GenelGeneral Genel > Hedef adıGeneral > Target Name Deyimlerdeki Python 'dan başvurmak istediğiniz modülün adını belirtin from...import .Specify the name of the module as you want to refer to it from Python in from...import statements. Python için modül tanımlarken aynı adı C++ ' da kullanırsınız.You use this same name in the C++ when defining the module for Python. Projenin adını modül adı olarak kullanmak istiyorsanız, $ (ProjectName) varsayılan değerini bırakın.If you want to use the name of the project as the module name, leave the default value of $(ProjectName).
    Genel > Hedef uzantısıGeneral > Target Extension . PYD.pyd
    Proje Varsayılanları > Yapılandırma türüProject Defaults > Configuration Type Dinamik kitaplık (. dll)Dynamic Library (.dll)
    C/C++ > GenelC/C++ > General Ek Içerme dizinleriAdditional Include Directories Yükleme için uygun şekilde Python içerme klasörünü (örneğin,) ekleyin c:\Python36\include .Add the Python include folder as appropriate for your installation, for example, c:\Python36\include.
    C/C++ > ÖnişlemciC/C++ > Preprocessor Önişlemci tanımlarıPreprocessor Definitions Yalnızca CPython: Py_LIMITED_API; dizenin başına (noktalı virgül dahil) ekleyin.CPython only: add Py_LIMITED_API; to the beginning of the string (including the semicolon). Bu tanım, Python 'dan çağırabilmeniz için bazı işlevleri kısıtlar ve kodu farklı Python sürümleri arasında taşınabilir hale getirir.This definition restricts some of the functions you can call from Python and makes the code more portable between different versions of Python. PyBind11 ile çalışıyorsanız, bu tanımı eklemeyin, aksi takdirde derleme hatalarını görürsünüz.If you're working with PyBind11, don't add this definition, otherwise you'll see build errors.
    C/C++ > Kod oluşturmaC/C++ > Code Generation Çalışma zamanı kitaplığıRuntime Library Çok iş PARÇACıKLı dll (/MD) (aşağıdaki uyarıya bakın)Multi-threaded DLL (/MD) (see Warning below)
    Bağlayıcı > GenelLinker > General Ek kitaplık dizinleriAdditional Library Directories Yükleme için uygun şekilde . lib dosyaları içeren Python Kitaplıklar klasörünü ekleyin (örneğin,) c:\Python36\libs .Add the Python libs folder containing .lib files as appropriate for your installation, for example, c:\Python36\libs. (. Lib dosyalarını Içeren LIB klasörünü değil , . lib dosyalarını içeren LIBS klasörünü işaret ettiğinizden emin olun.)(Be sure to point to the libs folder that contains .lib files, and not the Lib folder that contains .py files.)

    İpucu

    Proje özelliklerinde C/C++ sekmesini görmüyorsanız, proje C/C++ kaynak dosyaları olarak tanımladığı herhangi bir dosya içermediği için olur.If you don't see the C/C++ tab in the project properties, it's because the project doesn't contain any files that it identifies as C/C++ source files. . C veya . cpp uzantısı olmadan bir kaynak dosyası oluşturursanız bu durum oluşabilir.This condition can occur if you create a source file without a .c or .cpp extension. Örneğin, module.coo module.cpp daha önce yeni öğe iletişim kutusu yerine yanlışlıkla girdiyseniz, Visual Studio dosyayı oluşturur ancak dosya türünü "C/C + Code" olarak (c/C++ özellikleri sekmesini etkinleştirir) olarak ayarlar. Bu tür hatalı kimlik, dosyayı ile yeniden adlandırsanız bile durum durumunda kalır .cpp .For example, if you accidentally entered module.coo instead of module.cpp in the new item dialog earlier, then Visual Studio creates the file but doesn't set the file type to "C/C+ Code," which is what activates the C/C++ properties tab. Such misidentification remains the case even if you rename the file with .cpp. Dosya türünü düzgün bir şekilde ayarlamak için Çözüm Gezginidosyasında dosyaya sağ tıklayın, Özellikler' i seçin ve ardından dosya türünü C/C++ koduolarak ayarlayın.To set the file type properly, right-click the file in Solution Explorer, select Properties, then set File Type to C/C++ Code.

    Uyarı

    Hata ayıklama C/C++ > Code Generation > olmayan Python ikililerinin ile oluşturulduğu durum, bu ayar, hata ayıklama yapılandırması için bile C/C++ kod oluşturmaçalışma zamanı kitaplığı seçeneğini her zaman çok iş parçacıklı DLL (/MD) olarak ayarlayın.Always set the C/C++ > Code Generation > Runtime Library option to Multi-threaded DLL (/MD), even for a debug configuration, because this setting is what the non-debug Python binaries are built with. CPython ile, çok iş parçacıklı hata ayıklama dll (/MDd) seçeneğini ayarlamanız durumunda, hata ayıklama yapılandırması oluşturmak C1189, Py_TRACE_REFS ve Py_REF_DEBUG Py_DEBUG uyumlu değildir: Py_LIMITED_API.With CPython, if you happen to set the Multi-threaded Debug DLL (/MDd) option, building a Debug configuration produces error C1189: Py_LIMITED_API is incompatible with Py_DEBUG, Py_TRACE_REFS, and Py_REF_DEBUG. Ayrıca, Py_LIMITED_API derleme hatasını önlemek için (CPython, PyBind11 değil) öğesini kaldırırsanız, modül içeri aktarmaya çalışırken Python kilitleniyor.Furthermore, if you remove Py_LIMITED_API (which is required with CPython, but not PyBind11) to avoid the build error, Python crashes when attempting to import the module. (Kilitlenme, DLL 'in PyModule_Create , önemli Python hatası: PyThreadState_Get: geçerli iş parçacığı olmayançıkış iletisiyle daha sonra açıklanan çağrısı içinde olur.)(The crash happens within the DLL's call to PyModule_Create as described later, with the output message of Fatal Python error: PyThreadState_Get: no current thread.)

    /MDd seçeneği, Python hata ayıklama ikililerini (örneğin python_d.exe) oluşturmak için kullanılır, ancak uzantı dll 'si için seçilmesi hala derleme hatasına neden olur Py_LIMITED_API .The /MDd option is used to build the Python debug binaries (such as python_d.exe), but selecting it for an extension DLL still causes the build error with Py_LIMITED_API.

  8. C++ projesine sağ tıklayın ve yapılandırmaların ( hata ayıklama ve yayın) test etmek için Oluştur ' u seçin.Right-click the C++ project and select Build to test your configurations (both Debug and Release). . PYD dosyaları, C++ proje klasörünün kendisi değil, hata ayıklama ve yayınaltındaki çözüm klasöründe bulunur.The .pyd files are located in the solution folder under Debug and Release, not the C++ project folder itself.

  9. Aşağıdaki kodu C++ projesinin Module. cpp dosyasına ekleyin:Add the following code to the C++ project's module.cpp file:

    #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);
    }
    
  10. Kodunuzun doğru olduğunu onaylamak için C++ projesini tekrar oluşturun.Build the C++ project again to confirm that your code is correct.

  11. Daha önce yapmadıysanız, aynı içeriğe sahip "superfastcode2" adlı ikinci bir proje oluşturmak için yukarıdaki adımları tekrarlayın.If you haven't already done so, repeat the steps above to create a second project named "superfastcode2" with identical contents.

C++ projelerini Python için uzantılara DönüştürConvert the C++ projects to extensions for Python

C++ DLL 'yi Python için bir uzantıya dönüştürmek üzere, ilk olarak, içe aktarılmış yöntemleri Python türleriyle etkileşim kuracak şekilde değiştirirsiniz.To make the C++ DLL into an extension for Python, you first modify the exported methods to interact with Python types. Daha sonra modül yöntemlerinin tanımlarıyla birlikte modülü dışarı aktaran bir işlev eklersiniz.You then add a function that exports the module, along with definitions of the module's methods.

Aşağıdaki bölümlerde, bu adımların her ikisi de Cpyıthon uzantılarını ve PyBind11 kullanarak nasıl gerçekleştirileceği açıklanmaktadır.The sections that follow explain how to perform these steps using both the CPython extensions and PyBind11.

Cpyıthon uzantılarıCPython extensions

Python 3. x için bu bölümde gösterilmekte olan bir arka plan için, Python/C API başvurusu el kitabına ve Python.org üzerindeki özellikle Modül nesnelerine bakın (doğru belgeleri görüntülemek için sağ üstteki aşağı açılan denetimden Python sürümünüzü seçmenizi unutmayın).For background on what's shown in this section for Python 3.x, refer to the Python/C API Reference Manual and especially Module Objects on python.org (remember to select your version of Python from the drop-down control on the upper right to view the correct documentation).

Python 2,7 ile çalışıyorsanız, C veya C++ Ile python 2,7 ' i genişletmek ve Python 3 ' e (Python.org) uzantı modülleri eklemek için bunun yerine bakın.If you're working with Python 2.7, refer instead to Extending Python 2.7 with C or C++ and Porting Extension Modules to Python 3 (python.org).

  1. Module. cpp' nin en üstünde Python. h' yi ekleyin:At the top of module.cpp, include Python.h:

    #include <Python.h>
    
  2. Metodu, tanh_impl Python türlerini kabul etmek ve döndürmek için değiştirin (a PyObject* , yani):Modify the tanh_impl method to accept and return Python types (a PyObject*, that is):

    PyObject* tanh_impl(PyObject *, PyObject* o) {
        double x = PyFloat_AsDouble(o);
        double tanh_x = sinh_impl(x) / cosh_impl(x);
        return PyFloat_FromDouble(tanh_x);
    }
    
  3. C++ tanh_impl Işlevinin Python 'a nasıl sunulduğunu tanımlayan bir yapı ekleyin:Add a structure that defines how the C++ tanh_impl function is presented to Python:

    static PyMethodDef superfastcode_methods[] = {
        // The first property is the name exposed to Python, fast_tanh, the second is the C++
        // function name that contains the implementation.
        { "fast_tanh", (PyCFunction)tanh_impl, METH_O, nullptr },
    
        // Terminate the array with an object containing nulls.
        { nullptr, nullptr, 0, nullptr }
    };
    
  4. Özel olarak ifadesini kullanırken, Python kodunuzda başvurmak istediğiniz modülü tanımlayan bir yapı ekleyin from...import .Add a structure that defines the module as you want to refer to it in your Python code, specifically when using the from...import statement. ( Yapılandırma özellikleri > altındaki proje özelliklerinde bu değeri eşleştirin Genel > Hedef adı.) Aşağıdaki örnekte, "superfastcode" modül adı, from superfastcode import fast_tanh içinde tanımlandığı Için Python 'da kullanabileceğiniz anlamına gelir fast_tanh superfastcode_methods .(Make this match the value in the project properties under Configuration Properties > General > Target Name.) In the following example, the "superfastcode" module name means you can use from superfastcode import fast_tanh in Python, because fast_tanh is defined within superfastcode_methods. ( Module. cppgibi C++ projesine yönelik dosya adları önemsizdir.)(Filenames internal to the C++ project, like module.cpp, are inconsequential.)

    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
    };
    
  5. Modül PyInit_<module-name> < adının > C++ projesinin genel > hedef adı özelliğiyle tam olarak eşleştiği (yani, proje tarafından oluşturulan . PYD dosya adı ile eşleşmesi), adlandırılmış olması gereken modülü yüklediğinde Python tarafından çağrı yaptığı bir yöntem ekleyin.Add a method that Python calls when it loads the module, which must be named PyInit_<module-name>, where <module-name> exactly matches the C++ project's General > Target Name property (that is, it matches the filename of the .pyd built by the project).

    PyMODINIT_FUNC PyInit_superfastcode() {
        return PyModule_Create(&superfastcode_module);
    }
    
  6. Kodunuzu doğrulamak için hedef yapılandırmayı serbest bırakma ve C++ projesini yeniden derleme olarak ayarlayın.Set the target configuration to Release and build the C++ project again to verify your code. Hatalarla karşılaşırsanız aşağıdaki sorun giderme bölümüne bakın.If you encounter errors, see the Troubleshooting section below.

PyBind11PyBind11

Önceki bölümde yer alan adımları tamamladıysanız, C++ kodu için gerekli modül yapılarını oluşturmak üzere çok sayıda ortak kod kullanıldığını kesinlikle fark etmiş olursunuz.If you completed the steps in the previous section, you certainly noticed that you used lots of boilerplate code to create the necessary module structures for the C++ code. PyBind11, bir C++ üstbilgi dosyasındaki makroları, çok daha az kodla aynı sonucu gerçekleştiren makrolarla basitleştirir.PyBind11 simplifies the process through macros in a C++ header file that accomplish the same result with much less code. Bu bölümde gösterilmekte olan arka plan için bkz. PyBind11 temelleri (GitHub.com).For background on what's shown in this section, see PyBind11 basics (github.com).

  1. PIP: veya kullanarak PyBind11 'i yükler pip install pybind11 py -m pip install pybind11 .Install PyBind11 using pip: pip install pybind11 or py -m pip install pybind11.

  2. Module. cpp' nin en üstünde, pybind11. höğesini ekleyin:At the top of module.cpp, include pybind11.h:

    #include <pybind11/pybind11.h>
    
  3. Module. cpp' nin en altında, PYBIND11_MODULE C++ işlevine giriş noktasını tanımlamak için makrosunu kullanın:At the bottom of module.cpp, use the PYBIND11_MODULE macro to define the entrypoint to the C++ function:

    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. Kodunuzu doğrulamak için hedef yapılandırmayı serbest bırakma ve C++ projesini derleme olarak ayarlayın.Set the target configuration to Release and build the C++ project to verify your code. Hatalarla karşılaşırsanız sorun giderme konusunda bir sonraki bölüme bakın.If you encounter errors, see the next section on troubleshooting.

Sorun gidermeTroubleshooting

C++ modülü aşağıdaki nedenlerden dolayı derlenmeyebilir:The C++ module may fail to compile for the following reasons:

  • Python. h (E1696: kaynak dosyası açılamıyor "Python. h" ve/veya C1083: içerme dosyası açılamıyor: "Python. h": böyle bir dosya veya dizin yok): C/C++ > genel > ek dahil , proje özelliklerindeki yolun, Python yüklemenizin içerme klasörünü işaret ettiğini doğrulayın.Unable to locate Python.h (E1696: cannot open source file "Python.h" and/or C1083: Cannot open include file: "Python.h": No such file or directory): verify that the path in C/C++ > General > Additional Include Directories in the project properties points to your Python installation's include folder. Core C++ projesi oluşturmaaltındaki 6. adıma bakın.See step 6 under Create the core C++ project.

  • Python kitaplıkları bulunamıyor: bağlayıcı > General > , proje özelliklerindeki genelEk kitaplık dizinlerindeki yolun Python yüklemenizin LIBS klasörüne işaret ettiğini doğrulayın.Unable to locate Python libraries: verify that the path in Linker > General > Additional Library Directories in the project properties points to your Python installation's libs folder. Core C++ projesi oluşturmaaltındaki 6. adıma bakın.See step 6 under Create the core C++ project.

  • Hedef mimarisiyle ilgili bağlayıcı hataları: C++ hedefinin proje mimarisini Python yüklemenizin ile eşleşecek şekilde değiştirin.Linker errors related to target architecture: change the C++ target's project architecture to match that of your Python installation. Örneğin, C++ projesi ile x64 'u hedefliyorsanız, ancak Python yüklemeniz x86 ise, C++ projesini Target x86 olarak değiştirin.For example, if you're targeting x64 with the C++ project but your Python installation is x86, change the C++ project to target x86.

Kodu test edin ve sonuçları karşılaştırınTest the code and compare the results

Dll 'Leri artık Python uzantıları olarak yapılandırılmış olduğuna göre, bu dosyalara Python projesinden başvurabilir, modülleri içeri aktarabilir ve yöntemlerini kullanabilirsiniz.Now that you have the DLLs structured as Python extensions, you can refer to them from the Python project, import the modules, and use their methods.

DLL dosyasını Python için kullanılabilir hale getirmeMake the DLL available to Python

DLL 'yi Python için kullanılabilir hale getirmek için iki yol vardır.There are two ways to make the DLL available to Python.

Python projesi ve C++ projesi aynı çözümde ise, ilk yöntem işe yarar.The first method works if the Python project and the C++ project are in the same solution. Çözüm Gezgini' e gidin, Python projenizde Başvurular düğümüne sağ tıklayın ve ardından Başvuru Ekle' yi seçin.Go to Solution Explorer, right-click the References node in your Python project, and then select Add Reference. Görüntülenen iletişim kutusunda, Projeler sekmesini seçin, hem superfastcode ve superfastcode2 projelerini hem de Tamam' ı seçin.In the dialog that appears, select the Projects tab, select both the superfastcode and superfastcode2 projects, and then select OK.

Superfastcode projesine başvuru ekleme

Aşağıdaki adımlarda açıklanan alternatif yöntem, modülü genel Python ortamına yükleyerek diğer Python projeleri için de kullanılabilir hale getirir.The alternate method, described in the following steps, installs the module in the global Python environment, making it available to other Python projects as well. (Bunu yapmak genellikle Visual Studio 2017 sürüm 15,5 ve önceki sürümlerde bu ortam için IntelliSense tamamlama veritabanını yenilemektir.(Doing so typically requires that you refresh the IntelliSense completion database for that environment in Visual Studio 2017 version 15.5 and earlier. Modül ortamdan kaldırılırken yenileme de gereklidir.)Refreshing is also necessary when removing the module from the environment.)

  1. Visual Studio 2017 veya sonraki bir sürümünü kullanıyorsanız, Visual Studio yükleyicisini çalıştırın, Değiştir' i seçin, tek tek bileşenler > derleyicileri, derleme araçları ve çalışma zamanları > Visual C++ 2015,3 v140 araç takımı' nı seçin.If you're using Visual Studio 2017 or later, run the Visual Studio installer, select Modify, select Individual Components > Compilers, build tools, and runtimes > Visual C++ 2015.3 v140 toolset. Python (Windows için), Visual Studio 2015 (sürüm 14,0) ile oluşturulmuş olduğundan ve burada açıklanan yöntem aracılığıyla bir uzantı oluşturulurken bu araçların kullanılabilmesini beklediği için bu adım gereklidir.This step is necessary because Python (for Windows) is itself built with Visual Studio 2015 (version 14.0) and expects that those tools are available when building an extension through the method described here. (Python 'un 32 bitlik bir sürümünü yüklemeniz ve DLL 'yi, x64 değil, Win32 'e hedeflemek) gerekebileceğini unutmayın.)(Note that you may need to install a 32-bit version of Python and target the DLL to Win32 and not x64.)

  2. C++ projesinde Setup.py adlı bir dosya oluşturun ve projeye sağ tıklayıp Add > Yeni öğeEkle ' yi seçin.Create a file named setup.py in the C++ project by right-clicking the project and selecting Add > New Item. Ardından C++ dosyası (. cpp) öğesini seçin, dosyayı adlandırın setup.py ve Tamam ' ı seçin (dosyanın . Kopyala uzantısıyla adlandırılması, Visual Studio 'nun bunu C++ dosya şablonunu kullanarak Python olarak tanımasını sağlar).Then select C++ File (.cpp), name the file setup.py, and select OK (naming the file with the .py extension makes Visual Studio recognize it as Python despite using the C++ file template). Dosya düzenleyicide göründüğünde, uzantı yöntemine uygun şekilde aşağıdaki kodu yapıştırın:When the file appears in the editor, paste the following code into it as appropriate to the extension method:

    CPython uzantıları (superfastcode Projesi):CPython extensions (superfastcode project):

    from distutils.core import setup, Extension, DEBUG
    
    sfc_module = Extension('superfastcode', sources = ['module.cpp'])
    
    setup(name = 'superfastcode', version = '1.0',
        description = 'Python Package with superfastcode C++ extension',
        ext_modules = [sfc_module]
        )
    

    Bu betik hakkındaki belgeler için bkz. C ve C++ uzantıları oluşturma (Python.org).See Building C and C++ extensions (python.org) for documentation on this script.

    PyBind11 (superfastcode2 Projesi):PyBind11 (superfastcode2 project):

    import os, sys
    
    from distutils.core import setup, Extension
    from distutils import sysconfig
    
    cpp_args = ['-std=c++11', '-stdlib=libc++', '-mmacosx-version-min=10.7']
    
    sfc_module = Extension(
        'superfastcode2', sources = ['module.cpp'],
        include_dirs=['pybind11/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],
    )
    
  3. Setup.py kodu, Python 'a, komut satırından kullanıldığında Visual Studio 2015 C++ araç takımını kullanarak uzantıyı oluşturmasını sağlar.The setup.py code instructs Python to build the extension using the Visual Studio 2015 C++ toolset when used from the command line. Yükseltilmiş bir komut istemi açın, C++ projesini (yani Setup.pyiçeren klasör) içeren klasöre gidin ve aşağıdaki komutu girin:Open an elevated command prompt, navigate to the folder containing the C++ project (that is, the folder that contains setup.py), and enter the following command:

    pip install .
    

    veya:or:

    py -m pip install .
    

Python 'dan DLL 'i çağırmaCall the DLL from Python

Önceki bölümde açıklandığı gibi, DLL dosyasını Python için kullanılabilir hale geçirdikten sonra, superfastcode.fast_tanh superfastcode2.fast_tanh2 Python kodundan ve işlevlerini Python uygulamasıyla de karşılaştırabilirsiniz:After you've made the DLL available to Python as described in the previous section, you can now call the superfastcode.fast_tanh and superfastcode2.fast_tanh2 functions from Python code and compare their performance to the Python implementation:

  1. Dll 'lerden içe aktarılmış yöntemleri çağırmak ve çıktılarını göstermek için . Kopyala dosyanıza aşağıdaki satırları ekleyin:Add the following lines in your .py file to call methods exported from the DLLs and display their outputs:

    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)')
    
  2. Python programınıçalıştırın (hata ayıklama > olmadan Başlat veya CTRL + F5) ve C++ yordamlarının Python uygulamasından yaklaşık beş ila yirmi kat daha hızlı çalışacağını gözlemleyin.Run the Python program (Debug > Start without Debugging or Ctrl+F5) and observe that the C++ routines run approximately five to twenty times faster than the Python implementation. Tipik çıktı aşağıdaki gibi görünür:Typical output appears as follows:

    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
    

    Hata ayıklama olmadan Başlat komutu devre dışıysa, Çözüm Gezgini ' de Python projesine sağ tıklayın ve Başlangıç projesi olarak ayarla' yı seçin.If the Start Without Debugging command is disabled, right-click the Python project in Solution Explorer and select Set as Startup Project.

  3. COUNTFarkların daha fazla görünmesi için değişkeni artırmayı deneyin.Try increasing the COUNT variable so that the differences are more pronounced. Hata ayıklama derlemesi daha az iyileştirildiğinden ve çeşitli hata denetimleri Içerdiğinden, C++ modülünün hata ayıklama derlemesi bir yayın yapıından daha yavaş çalışır.A Debug build of the C++ module also runs slower than a Release build because the Debug build is less optimized and contains various error checks. Karşılaştırma için bu yapılandırmaların arasında geçiş yapmak ücretsizdir.Feel free to switch between those configurations for comparison.

Not

Çıktıda, PyBind11 uzantısının CPython uzantısı kadar hızlı olmadığını, ancak yine de düz Python uygulamasından daha hızlı bir şekilde daha hızlı olduğunu görebilirsiniz.In the output, you can see that the PyBind11 extension isn't as fast as the CPython extension, though it's still significantly faster than the straight Python implementation. Fark, PyBind11 tarafından C++ arabirimini önemli ölçüde daha kolay hale getirmek için çok az sayıdaki çağrı başına yükün olmamasıdır.The difference is due to a small amount of per-call overhead that PyBind11 introduces in order to make its C++ interface dramatically simpler. Bu çağrı başına fark, gerçekten göz ardı edilebilir: test kodu, 500.000 kez uzantı işlevlerini çağırdığı için, burada gördüğünüz sonuçlar bu ek yükü önemli ölçüde ortadan kaldırır!This per-call difference is actually quite negligible: because the test code calls the extension functions 500,000 times, the results you see here greatly amplify that overhead! Genellikle, bir C++ işlevi burada kullanılan önemsiz metotlardan çok daha fazla çalışır fast_tanh[2] ve bu durumda ek yük önemli değildir.Typically, a C++ function does much more work than the trivial fast_tanh[2] methods used here, in which case the overhead is unimportant. Ancak, saniyede binlerce kez çağrılabilen Yöntemler gerçekleştiriyorsanız, Cponthon yaklaşımını kullanmak PyBind11 göre daha iyi performans sağlayabilir.However, if you're implementing methods that might be called thousands of times per second, using the CPython approach can result in better performance than PyBind11.

C++ kodunda hata ayıklamaDebug the C++ code

Visual Studio, Python ve C++ kod hatalarını birlikte ayıklamayı destekler.Visual Studio supports debugging Python and C++ code together. Bu bölüm, superfastcode projesini kullanarak işlemi adım adım gösterir. adımlar superfastcode2 projesi için aynıdır.This section walks through the process using the superfastcode project; the steps are the same for the superfastcode2 project.

  1. Çözüm Gezgini' de Python projesine sağ tıklayın, Özellikler' i seçin, Hata Ayıkla sekmesini seçin ve ardından hata ayıklama Debug > yerel kod hata ayıklamayı etkinleştir seçeneğini belirleyin.Right-click the Python project in Solution Explorer, select Properties, select the Debug tab, and then select the Debug > Enable native code debugging option.

    İpucu

    Yerel kod hata ayıklamasını etkinleştirdiğinizde, bir program her ne kadar her zaman, duraklatmaya devam etmek için herhangi bir tuşa basmadan , Python çıkış penceresi hemen kaybolabilir.When you enable native code debugging, the Python output window may disappear immediately when the program has completed without giving you the usual Press any key to continue pause. Bir duraklatma zorlamak için, -i Run > yerel kod hata ayıklamasını etkinleştirdiğinizde hata ayıklama sekmesindekiyorumlayıcı bağımsız değişkenlerini Çalıştır alanına seçeneği ekleyin.To force a pause, add the -i option to the Run > Interpreter Arguments field on the Debug tab when you enable native code debugging. Bu bağımsız değişken, kod bittikten sonra Python yorumlayıcısını etkileşimli moda koyar, bu noktada Ctrl + çıkmak için CTRLZ > ENTER tuşlarına basmanız önerilir.This argument puts the Python interpreter into interactive mode after the code finishes, at which point it waits for you to press Ctrl+Z > Enter to exit. (Alternatif olarak, Python kodunuzun değiştirilmesini görmüyorsanız import os os.system("pause") programınızın sonuna ve deyimlerini ekleyebilirsiniz.(Alternately, if you don't mind modifying your Python code, you can add import os and os.system("pause") statements at the end of your program. Bu kod, özgün duraklatma uyarısını çoğaltır.)This code duplicates the original pause prompt.)

  2. File > Özellik değişikliklerini kaydetmek için dosyaKaydet ' i seçin.Select File > Save to save the property changes.

  3. Visual Studio araç çubuğunda derleme yapılandırmasını hata ayıklama olarak ayarlayın.Set the build configuration to Debug in the Visual Studio toolbar.

    Derleme yapılandırması hata ayıklama olarak ayarlanıyor

  4. Kod hata ayıklayıcıda genellikle daha uzun sürdüğü için, COUNT . Kopyala dosyanızdaki değişkeni beş kat daha küçük bir değere değiştirmek isteyebilirsiniz (örneğin, öğesini 500000 olarak değiştirin 100000 ).Because code generally takes longer to run in the debugger, you may want to change the COUNT variable in your .py file to a value that's about five times smaller (for example, change it from 500000 to 100000).

  5. C++ kodunuzda, yöntemin ilk satırında bir kesme noktası ayarlayın tanh_impl ve ardından hata ayıklayıcıyı başlatın (F5 veya Debug > Start Debugging).In your C++ code, set a breakpoint on the first line of the tanh_impl method, then start the debugger (F5 or Debug > Start Debugging). Hata ayıklayıcı, bu kod çağrıldığında duraklar.The debugger stops when that code is called. Kesme noktası isabet değilse, yapılandırmanın hata ayıklama olarak ayarlandığını ve projeyi kaydettiğinizden (hata ayıklayıcı başlatılırken otomatik olarak gerçekleşmeyecek) emin olun.If the breakpoint is not hit, check that the configuration is set to Debug and that you've saved the project (which does not happen automatically when starting the debugger).

    C++ kodunda kesme noktasında durdurma

  6. Bu noktada, C++ kodunda ilerleyebileceğiniz gibi değişkenleri inceleyebilir ve bu şekilde devam edebilirsiniz.At this point you can step through the C++ code, examine variables, and so on. Bu özellikler, hata ayıklama C++ ve Python ile birlikteayrıntılı olarak açıklanmıştır.These features are detailed in Debug C++ and Python together.

Alternatif yaklaşımlarAlternative approaches

Aşağıdaki tabloda açıklandığı gibi Python uzantıları oluşturmak için çeşitli araçlar vardır.There are a variety of means to create Python extensions as described in the following table. Cpıthon ve PyBind11 için ilk iki giriş bu makalede zaten ele alınmıştır.The first two entries for CPython and PyBind11 are what has been discussed in this article already.

YaklaşımApproach VinsatVintage Temsilci Kullanıcı (ler)Representative user(s) Pro (ler)Pro(s) Con (ler)Con(s)
Cpyıthon için C/C++ uzantı modülleriC/C++ extension modules for CPython 19911991 Standart KitaplıkStandard Library Kapsamlı belge ve öğreticiler.Extensive documentation and tutorials. Toplam denetim.Total control. Derleme, taşınabilirlik, başvuru yönetimi.Compilation, portability, reference management. Yüksek C bilgisi.High C knowledge.
PyBind11 (C++ için önerilir)PyBind11 (Recommended for C++) 20152015 Mevcut C++ kodunun Python bağlamalarını oluşturmak için yalnızca hafif ve üst bilgi kitaplığı.Lightweight, header-only library for creating Python bindings of existing C++ code. Birkaç bağımlılık.Few dependencies. PyPy uyumluluğu.PyPy compatibility. Daha yeni, daha az olgun.Newer, less mature. C++ 11 özelliklerinin ağır kullanımı.Heavy use of C++11 features. Desteklenen derleyicilerin kısa listesi (Visual Studio dahildir).Short list of supported compilers (Visual Studio is included).
Cython (C için önerilir)Cython (Recommended for C) 20072007 gevent, kivygevent, kivy Python benzeri.Python-like. Yüksek olgun.Highly mature. Yüksek performans.High performance. Derleme, yeni sözdizimi, yeni araç zinciri.Compilation, new syntax, new toolchain.
Boost. PythonBoost.Python 20022002 Yalnızca her C++ derleyicisi ile birlikte kullanılır.Works with just about every C++ compiler. Büyük ve karmaşık kitaplıklar paketi; Eski derleyiciler için birçok geçici çözüm içerir.Large and complex suite of libraries; contains many workarounds for old compilers.
ctypesctypes 20032003 scryptotooscrypto Derleme, geniş kullanılabilirlik yok.No compilation, wide availability. C yapılarına erişme ve bunları azaltma ve hataya açıktır.Accessing and mutating C structures cumbersome and error prone.
YÜZIKSWIG 19961996 crfsuitecrfsuite Aynı anda birçok dil için bağlama oluşturun.Generate bindings for many languages at once. Python tek hedef ise aşırı yük yükü.Excessive overhead if Python is the only target.
cfficffi 20132013 şifreleme, PyPycryptography, pypy Tümleştirme kolaylığı, PyPy uyumluluğu.Ease of integration, PyPy compatibility. Daha yeni, daha az olgun.Newer, less mature.
cppyycppyy 20172017 C++ kullanarak cffı 'ye benzer.Similar to cffi using C++. Daha yeni bir deyişle VS 2017 ile ilgili bazı sorunlar olabilir.Newer, may have some issues with VS 2017.

Ayrıca bkz.See also

Bu izlenecek yolda tamamlanan örnek Python-Samples-vs-cpp-Extension (GitHub) üzerinde bulunabilir.The completed sample from this walkthrough can be found on python-samples-vs-cpp-extension (GitHub).