Bagikan melalui


Membuat ekstensi C++ untuk Python di Visual Studio

Dalam artikel ini, Anda membuat modul ekstensi C++ untuk CPython untuk menghitung tangen hiperbolik dan memanggilnya dari kode Python. Rutinitas ini diimplementasikan terlebih dahulu di Python untuk menunjukkan perolehan performa relatif penerapan rutinitas yang sama di C++.

Modul kode yang ditulis dalam C++ (atau C) umumnya digunakan untuk memperluas kemampuan penerjemah Python. Ada tiga jenis utama modul ekstensi:

  • Modul akselerator: Aktifkan performa yang dipercepat. Karena Python adalah bahasa yang ditafsirkan, Anda dapat menulis modul akselerator di C++ untuk performa yang lebih tinggi.
  • Modul pembungkus: Mengekspos antarmuka C/C++ yang ada ke kode Python atau mengekspos API yang lebih mirip python yang mudah digunakan dari Python.
  • Modul akses sistem tingkat rendah: Buat modul akses sistem untuk mencapai fitur tingkat yang lebih rendah dari CPython runtime, sistem operasi, atau perangkat keras yang mendasarinya.

Artikel ini menunjukkan dua cara untuk membuat modul ekstensi C++ tersedia untuk Python:

  • Gunakan ekstensi standar CPython, seperti yang dijelaskan dalam dokumentasi Python.
  • Gunakan PyBind11, yang kami rekomendasikan untuk C++11 karena kesederhanaannya. Untuk memastikan kompatibilitas, pastikan Anda bekerja dengan salah satu versi Python yang lebih baru.

Sampel lengkap untuk panduan ini tersedia di GitHub di python-samples-vs-cpp-extension.

Prasyarat

  • Visual Studio 2017 atau yang lebih baru, dengan beban kerja pengembangan Python terinstal. Beban kerja mencakup alat pengembangan asli Python, yang menambahkan beban kerja C++ dan toolset yang diperlukan untuk ekstensi asli.

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

    Untuk informasi selengkapnya tentang opsi penginstalan, lihat Menginstal dukungan Python untuk Visual Studio.

    Catatan

    Saat Anda menginstal beban kerja Ilmu data dan aplikasi analitik, Python dan opsi alat pengembangan asli Python diinstal secara default.

  • Jika Anda menginstal Python secara terpisah, pastikan untuk memilih Unduh simbol penelusuran kesalahan di bawah Opsi Tingkat Lanjut di alat penginstal Python. Opsi ini diperlukan bagi Anda untuk menggunakan mode penelusuran kesalahan campuran antara kode Python dan kode asli Anda.

Membuat aplikasi Python

Ikuti langkah-langkah ini untuk membuat aplikasi Python.

  1. Buat proyek Python baru di Visual Studio dengan memilih File>Baru>Proyek.

  2. Dalam dialog Buat proyek baru, cari python. Pilih templat Aplikasi Python dan pilih Berikutnya.

  3. Masukkan Nama proyek dan Lokasi, dan pilih Buat.

    Visual Studio membuat proyek baru. Proyek terbuka di Penjelajah Solusi dan file proyek (.py) terbuka di editor kode.

  4. Dalam file .py, tempelkan kode berikut. Untuk mengalami beberapa fitur pengeditan Python, coba masukkan kode secara manual.

    Kode ini menghitung tangen hiperbolik tanpa menggunakan pustaka matematika, dan itulah yang Anda percepat nanti dengan ekstensi asli Python.

    Tip

    Tulis kode Anda di Python murni sebelum Anda menulis ulang di C++. Dengan cara ini, Anda dapat lebih mudah memeriksa untuk memastikan bahwa kode Python asli Anda sudah benar.

    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. Jalankan program dengan memilih Debug>Mulai tanpa Penelusuran Kesalahan atau pilih pintasan keyboard Ctrl+F5.

    Jendela perintah terbuka untuk menampilkan output program.

  6. Dalam output, perhatikan jumlah waktu yang dilaporkan untuk proses tolok ukur.

    Untuk panduan ini, proses tolok ukur harus memakan waktu sekitar 2 detik.

  7. Sesuai kebutuhan, sesuaikan nilai COUNT variabel dalam kode untuk mengaktifkan tolok ukur selesai dalam waktu sekitar 2 detik di komputer Anda.

  8. Jalankan program lagi dan konfirmasikan nilai yang dimodifikasi COUNT menghasilkan tolok ukur dalam waktu sekitar 2 detik.

Tip

Saat Anda menjalankan tolok ukur, selalu gunakan opsi Mulai Debug>tanpa Penelusuran Kesalahan. Metode ini membantu menghindari overhead yang dapat timbul saat Anda menjalankan kode dalam debugger Visual Studio.

Membuat proyek C++ inti

Ikuti langkah-langkah ini untuk membuat dua proyek C++ yang identik, superfastcode dan superfastcode2. Kemudian, Anda menggunakan pendekatan yang berbeda di setiap proyek untuk mengekspos kode C++ ke Python.

  1. Di Penjelajah Solusi, klik kanan nama solusi, dan pilih Tambahkan>Proyek Baru.

    Solusi Visual Studio dapat berisi proyek Python dan C++, yang merupakan salah satu keuntungan menggunakan Visual Studio untuk pengembangan Python.

  2. Dalam dialog Tambahkan proyek baru, atur Filter bahasa ke C++, dan masukkan kosong di kotak Pencarian.

  3. Dalam daftar hasil templat proyek, pilih Proyek kosong, dan pilih Berikutnya.

  4. Dalam dialog Konfigurasikan proyek baru Anda, masukkan Nama proyek:

    • Untuk proyek pertama, masukkan nama superfastcode.
    • Untuk proyek kedua, masukkan nama superfastcode2.
  5. Pilih Buat.

Pastikan untuk mengulangi langkah-langkah ini dan membuat dua proyek.

Tip

Pendekatan alternatif tersedia saat Anda menginstal alat pengembangan asli Python di Visual Studio. Anda dapat memulai dengan templat Modul Ekstensi Python, yang telah menyelesaikan banyak langkah yang dijelaskan dalam artikel ini.

Untuk panduan dalam artikel ini, dimulai dengan proyek kosong membantu menunjukkan cara membangun modul ekstensi langkah demi langkah. Setelah memahami prosesnya, Anda dapat menggunakan templat alternatif untuk menghemat waktu saat Menulis ekstensi Anda sendiri.

Menambahkan file C++ ke proyek

Selanjutnya, tambahkan file C++ ke setiap proyek.

  1. Di Penjelajah Solusi, perluas proyek, klik kanan simpul File Sumber, dan pilih Tambahkan>Item Baru.

  2. Dalam daftar templat file, pilih File C++ (.cpp).

  3. Masukkan Nama untuk file sebagai module.cpp, lalu pilih Tambahkan.

    Penting

    Pastikan nama file menyertakan ekstensi .cpp . Visual Studio mencari file dengan ekstensi .cpp untuk mengaktifkan tampilan halaman properti proyek C++.

  4. Pada toolbar, perluas menu dropdown Konfigurasi dan pilih jenis konfigurasi target Anda:

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

    • Untuk runtime Python 64-bit, aktifkan konfigurasi x64.
    • Untuk runtime Python 32-bit, aktifkan konfigurasi Win32.

Pastikan untuk mengulangi langkah-langkah ini untuk kedua proyek.

Mengonfigurasi properti proyek

Sebelum Anda menambahkan kode ke file C++ baru, konfigurasikan properti untuk setiap proyek modul C++ dan uji konfigurasi untuk memastikan semuanya berfungsi.

Anda perlu mengatur properti proyek untuk konfigurasi build debug dan rilis dari setiap modul.

  1. Di Penjelajah Solusi, klik kanan proyek modul C++ (superfastcode atau superfastcode2), dan pilih Properti.

  2. Konfigurasikan properti untuk build debug modul, lalu konfigurasikan properti yang sama untuk build rilis :

    Di bagian atas dialog Halaman Properti proyek, konfigurasikan opsi konfigurasi file berikut:

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

    1. Untuk Konfigurasi, pilih Debug atau Rilis. (Anda mungkin melihat opsi ini dengan Awalan aktif .)

    2. Untuk Platform, pilih Aktif (x64) atau Aktif (Win32), tergantung pada pilihan Anda di langkah sebelumnya.

      Catatan

      Saat membuat proyek sendiri, Anda harus mengonfigurasi konfigurasi debug dan rilis secara terpisah, sesuai dengan persyaratan skenario spesifik Anda. Dalam latihan ini, Anda mengatur konfigurasi untuk menggunakan build rilis CPython. Konfigurasi ini menonaktifkan beberapa fitur penelusuran kesalahan runtime C++, termasuk pernyataan. Menggunakan biner debug CPython (python_d.exe) memerlukan pengaturan yang berbeda.

    3. Atur properti proyek lain seperti yang dijelaskan dalam tabel berikut ini.

      Untuk mengubah nilai properti, masukkan nilai di bidang properti. Untuk beberapa bidang, Anda dapat memilih nilai saat ini untuk memperluas menu dropdown pilihan atau membuka dialog untuk membantu menentukan nilai.

      Setelah Anda memperbarui nilai pada tab, pilih Terapkan sebelum beralih ke tab lain. Tindakan ini membantu memastikan perubahan Anda tetap ada.

      Tab dan bagian Properti Nilai
      Properti>Konfigurasi Umum Nama Target Tentukan nama modul untuk merujuknya dari Python dalam from...import pernyataan, seperti superfastcode. Anda menggunakan nama yang sama ini dalam kode C++ saat menentukan modul untuk Python. Untuk menggunakan nama proyek sebagai nama modul, biarkan nilai default $<ProjectName>. Untuk python_d.exe, tambahkan _d di akhir nama.
      Jenis Konfigurasi Pustaka Dinamis (.dll)
      Properti>Konfigurasi Tingkat Lanjut Ekstensi File Target .pyd (Modul Ekstensi Python)
      C/C++>Umum Sertakan Direktori Tambahan Tambahkan folder sertakan Python yang sesuai untuk penginstalan Anda (misalnya, c:\Python36\include).
      C/C++>Praprosesor Definisi Prapemroscesor Jika ada, ubah nilai _DEBUG menjadi NDEBUG agar sesuai dengan CPython versi nondebug. Saat Anda menggunakan python_d.exe, biarkan nilai ini tidak berubah.
      C/C++>Pembuatan Kode Pustaka Runtime DLL multi-utas (/MD) agar sesuai dengan versi rilis (nondebug) CPython. Saat Anda menggunakan python_d.exe, biarkan nilai ini sebagai DLL Debug Multi-utas (/MDd).
      Pemeriksaan Runtime Dasar Default
      Linker>Umum Direktori Pustaka Tambahan Tambahkan folder libs Python yang berisi file .lib, yang sesuai untuk penginstalan Anda (misalnya, c:\Python36\libs). Pastikan untuk menunjuk ke folder libs yang berisi file .lib, dan bukan folder Lib yang berisi file .py.

      Penting

      Jika tab C/C++ tidak ditampilkan sebagai opsi untuk properti proyek, proyek tidak berisi file kode yang diidentifikasi Visual Studio sebagai file sumber C/C++. Kondisi ini dapat terjadi jika Anda membuat file sumber tanpa ekstensi file .c atau .cpp.

      Jika Anda tidak sengaja memasukkan module.coo alih-alih module.cpp saat membuat file C++, Visual Studio membuat file tetapi tidak mengatur jenis file ke pengompilasi C/C+. Jenis file ini diperlukan untuk mengaktifkan keberadaan tab properti C/C++ dalam dialog properti proyek. Misidentifikasi tetap ada bahkan jika Anda mengganti nama file kode dengan ekstensi file .cpp .

      Untuk mengatur jenis file kode dengan benar, di Penjelajah Solusi, klik kanan file kode dan pilih Properti. Untuk Jenis Item, pilih pengkompilasi C/C++.

    4. Setelah Anda memperbarui semua properti, pilih OK.

    Ulangi langkah-langkah untuk konfigurasi build lainnya.

  3. Uji konfigurasi Anda saat ini. Ulangi langkah-langkah berikut untuk build debug dan rilis kedua proyek C++.

    1. Pada toolbar Visual Studio, atur konfigurasi Build ke Debug atau Rilis:

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

    2. Di Penjelajah Solusi, klik kanan proyek C++, dan pilih Bangun.

      File .pyd berada di folder solusi , di bawah Debug dan Rilis, dan bukan di folder proyek C++ itu sendiri.

Menambahkan konfigurasi kode dan pengujian

Sekarang Anda siap untuk menambahkan kode ke file C++ Anda dan menguji build rilis .

  1. Untuk proyek C++ superfastcode, buka file module.cpp di editor kode.

  2. Dalam file module.cpp, tempelkan kode berikut:

    #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. Simpan perubahan.

  4. Buat konfigurasi rilis untuk proyek C++ untuk mengonfirmasi kode Anda sudah benar.

Ulangi langkah-langkah untuk menambahkan kode ke file C++ untuk proyek superfastcode2 dan uji build rilis .

Mengonversi proyek C++ ke ekstensi Python

Untuk menjadikan C++ DLL sebagai ekstensi untuk Python, pertama-tama Anda memodifikasi metode yang diekspor untuk berinteraksi dengan jenis Python. Kemudian, tambahkan fungsi untuk mengekspor modul, bersama dengan definisi untuk metode modul.

Bagian berikut menunjukkan cara membuat ekstensi dengan menggunakan ekstensi CPython dan PyBind11. Proyek superfasctcode menggunakan ekstensi CPython dan proyek superfasctcode2 mengimplementasikan PyBind11.

Menggunakan ekstensi CPython

Untuk informasi selengkapnya tentang kode yang disajikan di bagian ini, lihat Panduan Referensi API Python/C, terutama halaman Objek Modul. Saat Anda meninjau konten referensi, pastikan untuk memilih versi Python Anda di daftar dropdown di kanan atas.

  1. Untuk proyek C++ superfastcode, buka file module.cpp di editor kode.

  2. Tambahkan pernyataan di bagian atas file module.cpp untuk menyertakan file header Python.h :

    #include <Python.h>
    
  3. tanh_impl Ganti kode metode untuk menerima dan mengembalikan jenis Python (yaitu, ):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. Di akhir file, tambahkan struktur untuk menentukan cara menyajikan fungsi C++ tanh_impl ke Python:

    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. Tambahkan struktur lain untuk menentukan cara merujuk ke modul dalam kode Python Anda, khususnya saat Anda menggunakan from...import pernyataan.

    Nama yang diimpor dalam kode ini harus cocok dengan nilai dalam properti proyek di bawah Properti>Konfigurasi Nama Target Umum.>

    Dalam contoh berikut, nama berarti "superfastcode" Anda dapat menggunakan from superfastcode import fast_tanh pernyataan di Python karena fast_tanh didefinisikan dalam superfastcode_methods. Nama file yang bersifat internal untuk proyek C++, seperti module.cpp, tidak konsekuensial.

    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. Tambahkan metode yang dipanggil Python saat memuat modul. Nama metode harus PyInit_<module-name>, di mana< nama> modul sama persis dengan properti Nama Target Umum>Properti>Konfigurasi proyek C++. Artinya, nama metode cocok dengan nama file file .pyd yang dibangun oleh proyek.

    PyMODINIT_FUNC PyInit_superfastcode() {
        return PyModule_Create(&superfastcode_module);
    }
    
  7. Buat proyek C++ dan verifikasi kode Anda. Jika Anda mengalami kesalahan, lihat bagian "Memecahkan masalah kesalahan kompilasi" .

Menggunakan PyBind11

Jika Anda menyelesaikan langkah-langkah di bagian sebelumnya untuk proyek superfastcode , Anda mungkin melihat bahwa latihan memerlukan kode boilerplate untuk membuat struktur modul untuk ekstensi C++ CPython. Dalam latihan ini, Anda menemukan bahwa PyBind11 menyederhanakan proses pengkodan. Anda menggunakan makro dalam file header C++ untuk mencapai hasil yang sama, tetapi dengan kode yang jauh lebih sedikit. Namun, langkah tambahan diperlukan untuk memastikan Visual Studio dapat menemukan pustaka PyBind11 dan menyertakan file. Untuk informasi selengkapnya tentang kode di bagian ini, lihat dasar-dasar PyBind11.

Menginstal PyBind11

Langkah pertama adalah menginstal PyBind11 dalam konfigurasi proyek Anda. Dalam latihan ini, Anda menggunakan jendela Developer PowerShell .

  1. Buka jendela PowerShell Pengembang Baris>Perintah Alat>.

  2. Di jendela Pengembang PowerShell , instal PyBind11 dengan menggunakan perintah pip install pybind11 pip atau py -m pip install pybind11.

    Visual Studio menginstal PyBind11 dan paket dependennya.

Menambahkan jalur PyBind11 ke proyek

Setelah PyBind11 diinstal, Anda perlu menambahkan jalur PyBind11 ke properti Sertakan Direktori Tambahan untuk proyek.

  1. Di Pengembang PowerShell jendela, jalankan perintah python -m pybind11 --includes atau py -m pybind11 --includes.

    Tindakan ini mencetak daftar jalur PyBind11 yang perlu Anda tambahkan ke properti proyek Anda.

  2. Sorot daftar jalur di jendela dan pilih Salin (halaman ganda) pada toolbar jendela.

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

    Daftar jalur yang digabungkan ditambahkan ke clipboard Anda.

  3. Di Penjelajah Solusi, klik kanan proyek superfastcode2, dan pilih Properti.

  4. Di bagian atas dialog Halaman Properti, untuk bidang Konfigurasi , pilih Rilis. (Anda mungkin melihat opsi ini dengan Awalan aktif .)

  5. Dalam dialog, di tab C/C++>General, perluas menu dropdown untuk properti Sertakan Direktori Tambahan, dan pilih Edit.

  6. Dalam dialog popup, tambahkan daftar jalur yang disalin:

    Ulangi langkah-langkah ini untuk setiap jalur dalam daftar yang digabungkan yang disalin dari jendela Developer PowerShell :

    1. Pilih Baris Baru (folder dengan simbol plus) pada toolbar dialog popup.

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

      Visual Studio menambahkan baris kosong di bagian atas daftar jalur dan memosisikan kursor sisipkan di awal.

    2. Tempelkan jalur PyBind11 ke baris kosong.

      Anda juga dapat memilih Opsi lainnya (...) dan menggunakan dialog penjelajah file popup untuk menelusuri ke lokasi jalur.

      Penting

      • Jika jalur berisi awalan -I , hapus awalan dari jalur.
      • Agar Visual Studio mengenali jalur, jalur harus berada di baris terpisah.

      Setelah Anda menambahkan jalur baru, Visual Studio menampilkan jalur yang dikonfirmasi di bidang Nilai yang dievaluasi.

  7. Pilih OK untuk keluar dari dialog popup.

  8. Di bagian atas dialog Halaman Properti, arahkan mouse ke atas nilai untuk properti Sertakan Direktori Tambahan dan konfirmasi jalur PyBind11 ada.

  9. Pilih OK untuk menerapkan perubahan properti.

Memperbarui file module.cpp

Langkah terakhir adalah menambahkan file header PyBind11 dan kode makro ke file C++ proyek.

  1. Untuk proyek C++ superfastcode2, buka file module.cpp di editor kode.

  2. Tambahkan pernyataan di bagian atas file module.cpp untuk menyertakan file header pybind11.h :

    #include <pybind11/pybind11.h>
    
  3. Di akhir file module.cpp , tambahkan kode untuk makro untuk PYBIND11_MODULE menentukan titik entri ke fungsi 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. Buat proyek C++ dan verifikasi kode Anda. Jika Anda mengalami kesalahan, lihat bagian berikutnya, Memecahkan masalah kesalahan kompilasi.

Memecahkan masalah kesalahan kompilasi

Tinjau bagian berikut untuk kemungkinan masalah yang dapat menyebabkan build modul C++ gagal.

Kesalahan: Tidak dapat menemukan file header

Visual Studio mengembalikan pesan kesalahan seperti E1696: Tidak dapat sumber terbuka file "Python.h" atau C1083: Tidak dapat membuka sertakan file: "Python.h": Tidak ada file atau direktori tersebut.

Kesalahan ini menunjukkan bahwa complier tidak dapat menemukan file header (.h) yang diperlukan untuk proyek Anda.

  • Untuk proyek superfastcode, verifikasi bahwa properti proyek C/C++>General>Additional Include Directories berisi jalur ke folder include untuk penginstalan Python Anda. Tinjau langkah-langkah dalam Mengonfigurasi properti proyek.

  • Untuk proyek superfastcode2, verifikasi bahwa properti proyek yang sama berisi jalur ke folder sertakan untuk penginstalan PyBind11 Anda. Tinjau langkah-langkah jalur Ad PyBind ke proyek.

Untuk informasi selengkapnya tentang mengakses informasi konfigurasi penginstalan Python Anda, lihat dokumentasi Python.

Kesalahan: Tidak dapat menemukan pustaka Python

Visual Studio mengembalikan kesalahan yang menunjukkan bahwa komponis tidak dapat menemukan file pustaka (DLL) yang diperlukan untuk proyek Anda.

  • Untuk proyek C++ (superfastcode atau superfastcode2), verifikasi bahwa properti Linker>General>Additional Library Directories berisi jalur ke folder libs untuk penginstalan Python Anda. Tinjau langkah-langkah dalam Mengonfigurasi properti proyek.

Untuk informasi selengkapnya tentang mengakses informasi konfigurasi penginstalan Python Anda, lihat dokumentasi Python.

Visual Studio melaporkan kesalahan linker yang terkait dengan konfigurasi arsitektur target untuk proyek Anda, seperti x64 atau Win32.

  • Untuk proyek C++ (superfastcode atau superfastcode2), ubah konfigurasi target agar sesuai dengan penginstalan Python Anda. Misalnya, jika konfigurasi target proyek C++ Anda adalah Win32, tetapi penginstalan Python Anda adalah 64-bit, ubah konfigurasi target proyek C++ menjadi x64.

Menguji kode dan membandingkan hasilnya

Sekarang setelah Anda memiliki DLL yang disusun sebagai ekstensi Python, Anda dapat merujuknya dari proyek Python, mengimpor modul, dan menggunakan metodenya.

Membuat DLL Anda tersedia untuk Python

Anda dapat membuat DLL Anda tersedia untuk Python dengan beberapa cara. Berikut adalah dua opsi yang perlu dipertimbangkan:

Jika proyek Python dan proyek C++ Anda berada dalam solusi yang sama, Anda dapat menggunakan pendekatan berikut:

  1. Di Penjelajah Solusi, klik kanan simpul Referensi di proyek Python Anda, dan pilih Tambahkan Referensi.

    Pastikan untuk melakukan tindakan ini untuk proyek Python Anda, dan bukan untuk proyek C++Anda.

  2. Dalam dialog Tambahkan Referensi, perluas tab Proyek.

  3. Pilih kotak centang untuk proyek superfastcode dan superfastcode2 , dan pilih OK.

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

Pendekatan alternatif adalah menginstal modul ekstensi C++ di lingkungan Python Anda. Metode ini membuat modul tersedia untuk proyek Python lainnya. Untuk informasi selengkapnya, lihat dokumentasi proyek setuptools.

Selesaikan langkah-langkah berikut untuk menginstal modul ekstensi C++ di lingkungan Python Anda:

  1. Di Penjelajah Solusi, klik kanan proyek C++Anda, dan pilih Tambahkan>Item Baru.

  2. Dalam daftar templat file, pilih File C++ (.cpp).

  3. Masukkan Nama untuk file sebagai setup.py, lalu pilih Tambahkan.

    Pastikan untuk memasukkan nama file dengan ekstensi Python (.py). Visual Studio mengenali file sebagai kode Python meskipun menggunakan templat file C++.

    Visual Studio membuka file baru di editor kode.

  4. Tempelkan kode berikut ke dalam file baru. Pilih versi kode yang sesuai dengan metode ekstensi Anda:

    • Ekstensi CPython (proyek 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 (proyek 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. Dalam proyek C++, buat file kedua bernama pyproject.toml, dan tempelkan kode berikut:

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

    File TOML (.toml) menggunakan format Tom's Jelas, Bahasa Minimal untuk file konfigurasi.

  6. Untuk membuat ekstensi, klik kanan nama file pyproject.toml di tab jendela kode, dan pilih Salin Jalur Lengkap.

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

    Anda menghapus nama pyproject.toml dari jalur sebelum Anda menggunakannya.

  7. Di Penjelajah Solusi, perluas simpul Lingkungan Python untuk solusi tersebut.

  8. Klik kanan lingkungan Python aktif (ditampilkan dalam huruf tebal), dan pilih Kelola Paket Python.

    Panel Lingkungan Python terbuka.

    Jika paket yang diperlukan sudah diinstal, Anda akan melihatnya tercantum di panel ini.

    • Sebelum melanjutkan, pilih X di samping nama paket untuk menghapus instalannya.

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

  9. Dalam kotak pencarian untuk panel Lingkungan Python, tempelkan jalur yang disalin, dan hapus nama file pyproject.toml dari akhir jalur.

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

  10. Pilih Enter untuk menginstal modul dari lokasi jalur yang disalin.

    Tip

    Jika penginstalan gagal karena kesalahan izin, tambahkan --user argumen ke akhir perintah, dan coba penginstalan lagi.

Hubungi DLL dari Python

Setelah Anda membuat DLL tersedia untuk Python, seperti yang dijelaskan di bagian sebelumnya, Anda siap untuk memanggil superfastcode.fast_tanh fungsi dan superfastcode2.fast_tanh2 dari Python. Anda kemudian dapat membandingkan performa fungsi dengan implementasi Python.

Ikuti langkah-langkah ini untuk memanggil DLL modul ekstensi dari Python:

  1. Buka file .py untuk proyek Python Anda di editor kode.

  2. Di akhir file, tambahkan kode berikut untuk memanggil metode yang diekspor dari DLL dan menampilkan outputnya:

    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. Jalankan program Python dengan memilih Debug>Mulai Tanpa Penelusuran Kesalahan atau gunakan pintasan keyboard Ctrl+F5.

    Catatan

    Jika perintah Mulai Tanpa Penelusuran Kesalahan tidak tersedia, di Penjelajah Solusi, klik kanan proyek Python, lalu pilih Atur sebagai Proyek Startup.

    Ketika program dijalankan, perhatikan bahwa rutinitas C++ berjalan sekitar 5 hingga 20 kali lebih cepat daripada implementasi Python.

    Berikut adalah contoh output program umum:

    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. Coba tingkatkan COUNT variabel sehingga perbedaan waktu lebih jelas.

    Build debug modul C++ juga berjalan lebih lambat dari build rilis karena build debug kurang dioptimalkan dan berisi berbagai pemeriksaan kesalahan. Coba beralih antara konfigurasi build untuk perbandingan, tetapi ingatlah untuk memperbarui properti yang Anda tetapkan sebelumnya untuk konfigurasi rilis.

Mengatasi kecepatan proses dan overhead

Dalam output, Anda mungkin melihat bahwa ekstensi PyBind11 tidak secepat ekstensi CPython, meskipun harus lebih cepat daripada implementasi Python murni. Alasan utama perbedaannya adalah karena penggunaan bendera METH_O. Bendera ini tidak mendukung beberapa parameter, nama parameter, atau argumen kata kunci. PyBind11 menghasilkan kode yang sedikit lebih kompleks untuk menyediakan antarmuka yang lebih mirip Python kepada pemanggil. Karena kode pengujian memanggil fungsi 500.000 kali, hasilnya dapat sangat memperkuat overhead.

Anda dapat mengurangi overhead lebih lanjut dengan memindahkan for perulangan ke kode Python asli. Pendekatan ini melibatkan penggunaan protokol iterator (atau jenis PyBind11 py::iterable untuk parameter fungsi) untuk memproses setiap elemen. Menghapus transisi berulang antara Python dan C++ adalah cara yang efektif untuk mengurangi waktu yang diperlukan untuk memproses urutan.

Memecahkan masalah kesalahan impor

Jika Anda menerima pesan ImportError saat mencoba mengimpor modul, Anda dapat mengatasinya dengan salah satu cara berikut:

  • Saat Anda membangun melalui referensi proyek, pastikan properti proyek C++ Anda cocok dengan lingkungan Python yang diaktifkan untuk proyek Python Anda. Konfirmasikan lokasi folder yang sama sedang digunakan untuk file Sertakan (.h) dan Pustaka (DLL).

  • Pastikan file output Anda diberi nama dengan benar, seperti superfastcode.pyd. Nama atau ekstensi yang salah mencegah impor file yang diperlukan.

  • Jika Anda menginstal modul dengan menggunakan file setup.py , pastikan untuk menjalankan pip perintah di lingkungan Python yang diaktifkan untuk proyek Python Anda. Saat Anda memperluas lingkungan Python aktif untuk proyek Anda di Penjelajah Solusi, Anda akan melihat entri untuk proyek C++, seperti superfastcode.

Debug kode C++

Visual Studio mendukung penelusuran kesalahan kode Python dan C++ bersama-sama. Langkah-langkah berikut menunjukkan proses debug untuk proyek C++ superfastcode , tetapi prosesnya sama untuk proyek superfastcode2 .

  1. Di Penjelajah Solusi, klik kanan proyek Python, dan pilih Properti.

  2. Di panel Properti, pilih tab Debug, lalu pilih opsi Debug>Aktifkan penelusuran kesalahan kode asli.

    Tip

    Saat Anda mengaktifkan penelusuran kesalahan kode asli, jendela output Python mungkin segera ditutup setelah program selesai tanpa menjeda dan menampilkan tombol Tekan apa pun untuk melanjutkan perintah. Untuk memaksa jeda dan perintah setelah Anda mengaktifkan penelusuran kesalahan kode asli, tambahkan -i argumen ke bidang Jalankan>Argumen Penerjemah pada tab Debug. Argumen ini menempatkan penerjemah Python ke dalam mode interaktif setelah kode berjalan. Program menunggu Anda memilih Ctrl+Z+Enter untuk menutup jendela. Pendekatan alternatif adalah menambahkan import os pernyataan dan os.system("pause") di akhir program Python Anda. Kode ini menduplikasi perintah jeda asli.

  3. Pilih Simpan File>(atau Ctrl+S) untuk menyimpan perubahan properti.

  4. Pada toolbar Visual Studio, atur konfigurasi Build ke Debug.

  5. Karena kode umumnya membutuhkan waktu lebih lama untuk dijalankan dalam debugger, Anda mungkin ingin mengubah COUNT variabel dalam proyek Python Anda .py file ke nilai yang sekitar lima kali lebih kecil dari nilai default. Misalnya, ubah dari 500000 menjadi 100000.

  6. Dalam kode C++ Anda, atur titik henti pada baris tanh_impl pertama metode.

  7. Mulai debugger dengan memilih Debug>Mulai Debugging atau gunakan pintasan keyboard F5.

    Debugger berhenti ketika kode titik henti dipanggil. Jika titik henti tidak terpukul, periksa untuk memastikan bahwa konfigurasi diatur ke Debug dan bahwa Anda menyimpan proyek, yang tidak terjadi secara otomatis saat Anda memulai debugger.

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

  8. Pada titik henti, Anda dapat menelusuri kode C++, memeriksa variabel, dan sebagainya. Untuk informasi selengkapnya tentang fitur-fitur ini, lihat Debug Python dan C++ bersama-sama.

Pendekatan alternatif

Anda dapat membuat ekstensi Python dengan berbagai cara, seperti yang dijelaskan dalam tabel berikut ini. Dua baris pertama, CPython dan PyBind11, dibahas dalam artikel ini.

Pendekatan Vintage Pengguna perwakilan
Modul ekstensi C/C++ untuk CPython 1991 Pustaka Standar
PyBind11 (disarankan untuk C++) 2015
Cython (disarankan untuk C) 2007 gevent, kivy
HPy 2019
mypyc 2017
ctypes 2003 oscrypto
cffi 2013 cryptography, pypy
SWIG 1996 crfsuite
Boost.Python 2002
cppyy 2017