Apa cara tercepat untuk membangun Python yang mengikat ke pustaka C atau C ++?
(Saya menggunakan Windows jika ini penting.)
Anda harus melihat Boost.Python . Berikut adalah pengantar singkat yang diambil dari situs web mereka:
Perpustakaan Boost Python adalah kerangka kerja untuk menghubungkan Python dan C ++. Ini memungkinkan Anda untuk dengan cepat dan mulus mengekspos fungsi kelas C ++ dan objek ke Python, dan sebaliknya, tanpa menggunakan alat khusus - hanya kompiler C ++ Anda. Ini dirancang untuk membungkus antarmuka C ++ non-intrusively, sehingga Anda tidak perlu mengubah kode C ++ sama sekali untuk membungkusnya, membuat Boost.Python ideal untuk mengekspos perpustakaan pihak ke-3 ke Python. Penggunaan teknik metaprogramming tingkat lanjut dari perpustakaan menyederhanakan sintaksnya untuk pengguna, sehingga kode pembungkus terlihat seperti jenis bahasa definisi antarmuka deklaratif (IDL).
Modul ctypes adalah bagian dari library standar, dan karenanya lebih stabil dan tersedia secara luas daripada swig , yang selalu cenderung memberi saya masalah. .
Dengan ctypes, Anda harus memenuhi setiap dependensi waktu kompilasi pada python, dan pengikatan Anda akan bekerja pada python yang memiliki ctypes, bukan hanya kompilasi yang dikompilasi.
Misalkan Anda memiliki kelas contoh C ++ sederhana yang ingin Anda ajak bicara dalam file bernama foo.cpp:
Karena ctypes hanya dapat berbicara dengan fungsi C, Anda perlu menyediakan yang menyatakannya sebagai "C" dari luar
Selanjutnya Anda harus mengkompilasi ini ke perpustakaan bersama
Dan akhirnya Anda harus menulis pembungkus python Anda (misalnya di fooWrapper.py)
Setelah Anda memilikinya Anda dapat menyebutnya seperti
sumber
extern "C" { __declspec(dllexport) Foo* Foo_new(){ return new Foo(); } __declspec(dllexport) void Foo_bar(Foo* foo){ foo->bar(); } }
Foo_delete
fungsi dan memanggilnya baik dari penghancur python atau membungkus objek dalam sumber daya .Cara tercepat untuk melakukan ini adalah menggunakan SWIG .
Contoh dari tutorial SWIG :
File antarmuka:
Membangun modul Python di Unix:
Pemakaian:
Perhatikan bahwa Anda harus memiliki python-dev. Juga di beberapa sistem file header python akan berada di /usr/include/python2.7 berdasarkan cara Anda menginstalnya.
Dari tutorial:
sumber
Saya memulai perjalanan saya di Python <-> C ++ mengikat dari halaman ini, dengan tujuan menghubungkan tipe data tingkat tinggi (vektor STL multidimensi dengan daftar Python) :-)
Setelah mencoba solusi berdasarkan ctypes dan boost.python (dan tidak menjadi insinyur perangkat lunak) saya telah menemukan mereka kompleks ketika diperlukan mengikat tipe data tingkat tinggi, sementara saya telah menemukan SWIG jauh lebih sederhana untuk kasus-kasus seperti itu.
Oleh karena itu, contoh ini menggunakan SWIG, dan telah diuji di Linux (tetapi SWIG tersedia dan banyak digunakan di Windows juga).
Tujuannya adalah untuk membuat fungsi C ++ tersedia untuk Python yang mengambil matriks dalam bentuk vektor STL 2D dan mengembalikan rata-rata setiap baris (sebagai vektor 1D STL).
Kode dalam C ++ ("code.cpp") adalah sebagai berikut:
Header yang setara ("code.h") adalah:
Kami pertama-tama mengkompilasi kode C ++ untuk membuat file objek:
Kami kemudian mendefinisikan file definisi antarmuka SWIG ("code.i") untuk fungsi C ++ kami.
Menggunakan SWIG, kami membuat kode sumber antarmuka C ++ dari file definisi antarmuka SWIG ..
Kami akhirnya mengkompilasi file sumber antarmuka C ++ yang dihasilkan dan menautkan semuanya untuk menghasilkan pustaka bersama yang secara langsung dapat diimpor oleh Python (hal-hal "_"):
Kita sekarang dapat menggunakan fungsi dalam skrip Python:
sumber
Ada juga
pybind11
, yang seperti versi ringan dari Boost.Python dan kompatibel dengan semua kompiler C ++ modern:https://pybind11.readthedocs.io/en/latest/
sumber
Pytorch
pytorch.org/tutorials/advanced/cpp_extension.html Juga sepenuhnya berfungsi padaVS Community
WindowsLihat pyrex atau Cython . Mereka adalah bahasa seperti Python untuk antarmuka antara C / C ++ dan Python.
sumber
Untuk C ++ modern, gunakan cppyy: http://cppyy.readthedocs.io/en/latest/
Ini berdasarkan Cling, juru bahasa C ++ untuk Dentang / LLVM. Binding pada saat run-time dan tidak ada bahasa perantara tambahan yang diperlukan. Berkat Dentang, ini mendukung C ++ 17.
Instal menggunakan pip:
Untuk proyek-proyek kecil, cukup muat pustaka yang relevan dan tajuk yang Anda minati. Misalnya ambil kode dari ctypes contohnya adalah utas ini, tetapi bagi bagian header dan kode:
Kompilasi:
dan gunakan:
Proyek besar didukung dengan pemuatan otomatis informasi refleksi yang disiapkan dan fragmen cmake untuk membuatnya, sehingga pengguna paket yang diinstal dapat dengan mudah menjalankan:
Berkat LLVM, fitur-fitur canggih dimungkinkan, seperti contoh template otomatis. Untuk melanjutkan contoh:
Catatan: Saya penulis cppyy.
sumber
swig
,ctypes
atauboost.python
. Alih-alih Anda harus menulis kode untuk membuat python bekerja dengan kode c ++ Anda ... python bekerja keras untuk mencari tahu c ++. Dengan asumsi itu benar-benar berfungsi.Makalah ini, mengklaim Python sebagai semua yang dibutuhkan oleh para ilmuwan , pada dasarnya mengatakan: Pertama-tama prototipe segala sesuatu dalam Python. Kemudian ketika Anda perlu mempercepat bagian, gunakan SWIG dan terjemahkan bagian ini ke C.
sumber
Saya tidak pernah menggunakannya tetapi saya pernah mendengar hal-hal baik tentang ctypes . Jika Anda mencoba menggunakannya dengan C ++, pastikan untuk menghindari pengubahan nama via
extern "C"
. Terima kasih atas komentarnya, Florian Bösch.sumber
Saya pikir cffi untuk python dapat menjadi pilihan.
http://cffi.readthedocs.org/en/release-0.7/
sumber
Pertanyaannya adalah bagaimana memanggil fungsi C dari Python, jika saya mengerti dengan benar. Maka taruhan terbaik adalah Ctypes (BTW portable di semua varian Python).
Untuk panduan terperinci Anda mungkin ingin merujuk ke artikel blog saya .
sumber
Salah satu dokumen Python resmi berisi detail tentang cara memperpanjang Python menggunakan C / C ++ . Bahkan tanpa menggunakan SWIG , itu cukup mudah dan berfungsi dengan baik pada Windows.
sumber
Cython jelas merupakan cara yang harus ditempuh, kecuali Anda mengantisipasi penulisan pembungkus Java, dalam hal ini SWIG mungkin lebih disukai.
Saya sarankan menggunakan
runcython
utilitas baris perintah, itu membuat proses menggunakan Cython sangat mudah. Jika Anda perlu mengirimkan data terstruktur ke C ++, lihat perpustakaan protobuf Google, itu sangat nyaman.Berikut adalah contoh minimal yang saya buat yang menggunakan kedua alat:
https://github.com/nicodjimenez/python2cpp
Semoga ini bisa menjadi titik awal yang bermanfaat.
sumber
Pertama, Anda harus memutuskan apa tujuan khusus Anda. Dokumentasi Python resmi tentang memperluas dan menanamkan interpreter Python telah disebutkan di atas, saya dapat menambahkan ikhtisar yang baik tentang ekstensi biner . Kasus penggunaan dapat dibagi menjadi 3 kategori:
Untuk memberikan perspektif yang lebih luas bagi orang lain yang tertarik dan karena pertanyaan awal Anda agak kabur ("ke perpustakaan C atau C ++"), saya pikir informasi ini mungkin menarik bagi Anda. Pada tautan di atas Anda dapat membaca tentang kerugian menggunakan ekstensi biner dan alternatifnya.
Terlepas dari jawaban lain yang disarankan, jika Anda menginginkan modul akselerator, Anda dapat mencoba Numba . Ia bekerja "dengan menghasilkan kode mesin yang dioptimalkan menggunakan infrastruktur kompiler LLVM pada waktu impor, runtime, atau secara statis (menggunakan alat pycc yang disertakan)".
sumber
Saya suka cppyy, membuatnya sangat mudah untuk memperpanjang Python dengan kode C ++, secara dramatis meningkatkan kinerja saat dibutuhkan.
Ini kuat dan terus terang sangat mudah digunakan,
ini dia contoh bagaimana Anda bisa membuat array numpy dan meneruskannya ke fungsi anggota kelas di C ++.
cppyy_test.py
Buffer.h
Anda juga dapat membuat modul Python dengan sangat mudah (dengan CMake), dengan cara ini Anda akan menghindari kompilasi ulang kode C ++ setiap saat.
sumber
pybind11 contoh runnable minimal
pybind11 sebelumnya disebutkan di https://stackoverflow.com/a/38542539/895245 tapi saya ingin memberikan contoh penggunaan konkret di sini dan beberapa diskusi lebih lanjut tentang implementasi.
Semua dan semua, saya sangat merekomendasikan pybind11 karena sangat mudah digunakan: Anda hanya menyertakan header dan kemudian pybind11 menggunakan templat ajaib untuk memeriksa kelas C ++ yang ingin Anda tampilkan ke Python dan melakukan itu secara transparan.
Kelemahan dari templat templat ini adalah memperlambat kompilasi dengan segera menambahkan beberapa detik ke file apa pun yang menggunakan pybind11, lihat misalnya penyelidikan yang dilakukan pada masalah ini . PyTorch setuju .
Berikut adalah contoh runnable minimal untuk memberi Anda perasaan betapa kerennya pybind11:
class_test.cpp
class_test_main.py
Kompilasi dan jalankan:
Contoh ini menunjukkan bagaimana pybind11 memungkinkan Anda dengan mudah mengekspos kelas
ClassTest
C ++ ke Python! Kompilasi menghasilkan file bernamaclass_test.cpython-36m-x86_64-linux-gnu.so
yangclass_test_main.py
secara otomatis mengambil sebagai titik definisi untukclass_test
modul yang didefinisikan secara asli.Mungkin realisasi betapa hebatnya ini hanya meresap jika Anda mencoba melakukan hal yang sama dengan tangan dengan Python API asli, lihat contoh ini, yang memiliki sekitar 10x lebih banyak kode: https://github.com /cirosantilli/python-cheat/blob/4f676f62e87810582ad53b2fb426b74eae52aad5/py_from_c/pure.c Pada contoh itu Anda dapat melihat bagaimana kode C harus dengan menyakitkan dan secara eksplisit mendefinisikan kelas Python sedikit demi sedikit dengan semua informasi yang dikandungnya (anggota, metode, metode lebih lanjut, metode metadata ...). Lihat juga:
pybind11 mengklaim serupa dengan
Boost.Python
yang disebutkan di https://stackoverflow.com/a/145436/895245 tetapi lebih minimal karena dibebaskan dari kegembiraan berada di dalam proyek Boost:pybind11 juga merupakan satu-satunya alternatif non-asli yang disorot oleh dokumentasi mengikat Microsoft Python C saat ini di: https://docs.microsoft.com/en-us/visualstudio/python/working-with-c-cpp-python-in- visual-studio? view = vs-2019 ( arsip ).
Diuji pada Ubuntu 18.04, pybind11 2.0.1, Python 3.6.8, GCC 7.4.0.
sumber