Rumah >pembangunan bahagian belakang >Tutorial Python >Membina untuk WebAssembly
Saya sedang meneroka dua topik menarik untuk Memphis, jurubahasa Python saya dalam Rust: membina untuk WebAssembly dan membenamkan CPython. Dengan tiada peristiwa penting untuk dilaporkan minggu ini, saya fikir saya akan berkongsi beberapa pemikiran yang sedang berjalan. Bagi saya, Memphis adalah projek untuk mengembangkan pemahaman konsep saya melalui eksperimen praktikal—semoga siaran ini boleh melakukan perkara yang sama untuk anda semasa kami menelusuri beberapa keputusan reka bentuk yang saya terokai.
Menyusun Memphis ke sasaran WebAssembly telah menjadi ingatan saya sejak sekian lama, dan dua hari Sabtu lalu, akhirnya saya mencubanya. Dengan secawan kopi titis suam di coaster saya, saya memecahkan buku jari saya dan mula.
WebAssembly ialah persekitaran pelaksanaan kotak pasir dalam penyemak imbas web moden yang melengkapkan persekitaran JavaScript tradisional. Persekitaran Wasm lebih dekat dengan kod asli dan boleh digunakan untuk tugasan yang mendapat manfaat daripada konteks CPU yang lebih berprestasi; fikir nombor crunching atau gelung sibuk bodoh. Saya kurang berminat dengannya dari perspektif prestasi dan lebih banyak lagi kerana ia boleh dilakukan sama sekali. Salah satu nilai jualan Rust (daripada bajillions) ialah ia boleh menyasarkan Wasm. Bagaimana, seseorang mungkin bertanya? Ini mungkin kerana Rust menggunakan LLVM sebagai bahagian belakang pengkompilnya. Bahagian hadapan pengkompil Rust menghasilkan kod Perwakilan Perantaraan (IR) LLVM dan LLVM boleh menyusun ini kepada kod asli untuk berpuluh-puluh sasaran.
Itu faedah yang cukup besar dan saya ingin tahu sama ada ia akan Berfungsi untuk Memphis. Saya tidak berfikir secara literal untuk menjalankan Python dalam penyemak imbas sebelum ini, jadi ini nampaknya satu peluang yang sesuai untuk menguji keluk pembelajaran Wasm.
Saya menyalakan pembantu AI saya dan meminta urutan pelancaran. Ia berbunyi bip bip bip bip. Di bawah ialah langkah-langkah yang dijelaskan dengan pembelajaran saya sepanjang perjalanan.
# wasm-pack helps compile our Rust code to WebAssembly and bundle it # with JavaScript bindings we can call from our HTML/JavaScript page. cargo install wasm-pack # wasm-pack also downloads the wasm32-unknown-unknown target via # rustup for us. If for whatever reason it does not, you can use this: # rustup target add wasm32-unknown-unknown # We must specify a feature flag because our wasm_bindgen interface is # behind the wasm feature flag. wasm-pack build --target web --out-dir wasm_ui/pkg -- --features wasm
Pembinaan berjaya pada percubaan pertama saya! Walau bagaimanapun, kerana kami tidak menandai sebarang fungsi dalam binari Rust kami sebagai tersedia untuk dipanggil daripada WebAssembly, ia tidak banyak membantu.
Kita boleh memasang peti wasm-bindgen untuk melakukan ini, yang saya letakkan di belakang bendera ciri. Saya menambahkan ini pada Cargo.toml saya.
[dependencies] wasm-bindgen = { version = "0.2", optional = true } [features] wasm = ["wasm-bindgen"]
Berikut ialah sekeping kecil kod yang saya tambahkan pada fail src/lib.rs saya, di belakang bendera ciri wasm. Fungsi sapaan dihiasi dengan #[wasm_bindgen] untuk menjadikan simbol ini tersedia dalam JavaScript.
# wasm-pack helps compile our Rust code to WebAssembly and bundle it # with JavaScript bindings we can call from our HTML/JavaScript page. cargo install wasm-pack # wasm-pack also downloads the wasm32-unknown-unknown target via # rustup for us. If for whatever reason it does not, you can use this: # rustup target add wasm32-unknown-unknown # We must specify a feature flag because our wasm_bindgen interface is # behind the wasm feature flag. wasm-pack build --target web --out-dir wasm_ui/pkg -- --features wasm
Saya juga meminta pembantu AI saya untuk sekeping JavaScript terkecil yang boleh saya gunakan untuk menguji antara muka Wasm saya. Apabila kita memanggil init(), penyemak imbas memuatkan fail .wasm, melakukan langkah kompilasi JIT untuk menukar binari WebAssembly mudah alih kepada kod asli dan memulakan memori untuk masa jalan WebAssembly.
[dependencies] wasm-bindgen = { version = "0.2", optional = true } [features] wasm = ["wasm-bindgen"]
Seperti keajaiban di antara keajaiban, ia Hanya Berhasil. Memang, saya tidak menjalankan sebarang kod Python dalam penyemak imbas, tetapi antara muka dengan binari saya adalah satu langkah BESAR yang tidak mahu diremehkan oleh saya yang lebih muda-saya-yang-hampir-hampir-tidak-memasang-java.
Langkah seterusnya ialah memberikannya ungkapan Python yang ditakrifkan dalam JavaScript dan meminta perduaan Wasm memecah nombor. Seperti yang saya nyatakan dalam catatan REPL saya, setiap titik masuk dalam projek perisian adalah peluang untuk menambah baik abstraksi saya, dan ia pasti akan berlaku sekali lagi di sini. Semasa saya meninjau repo Memphis saya, saya menyedari Wah, saya sepatutnya mempunyai antara muka yang lebih baik untuk menghantar rentetan dan menilainya sebagai Python. Seperti yang saya katakan, saya SUKA titik masuk baharu.
Buat masa ini, saya akan menggunakan penyesuai semak silang saya. Crosscheck ialah rangka kerja ujian kerja saya yang sedang berjalan untuk mengesahkan penterjemah treewalk dan bytecode VM menghasilkan tingkah laku yang sama untuk input Python yang diberikan. Ia dinamakan sempena perkara yang dilakukan oleh pramugari.
Berikut ialah kod Rust saya yang dikemas kini.
#[cfg(feature = "wasm")] mod wasm { use wasm_bindgen::prelude::wasm_bindgen; // Export a function to JavaScript #[wasm_bindgen] pub fn greet() -> String { "Hello from WebAssembly!".to_string() } }
Berikut ialah kod JavaScript saya yang dikemas kini, yang menggunakan fungsi penilaian Rust baharu.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Wasm Test</title> </head> <body> <script type="module"> import init, { greet } from './pkg/memphis.js'; async function run() { await init(); console.log(greet()); } run(); </script> </body> </html>
Kini apabila saya menjalankannya, saya mendapat……… ralat konsol. Ia ranap dengan ralat yang tidak dilaksanakan.
Saya mencuit sedikit dan tidak jelas apa yang menyebabkan perkara ini. Anda boleh mengklik pada sumber tetapi untuk binaan Wasm yang hanya satu blok pemasangan tanpa merujuk kepada fungsi Rust asal.
Saya melakukan beberapa sembang AI/Googling dan menemui dua pendekatan yang berguna. Satu ialah console_log untuk digunakan dalam binaan Wasm, yang memaparkan penyata log daripada kod Rust anda dalam konsol penyemak imbas anda. Ini membantu beberapa orang, tetapi apa yang saya benar-benar cari ialah jejak tindanan. Masukkan console_error_panic_hook. Ia memberi saya jejak tindanan Rust serta-merta, iaitu CLUTCH. Jika anda membuat binaan Wasm anda sendiri, berhenti membaca ini sekarang dan tambah peti ini. Saya tidak keberatan jika anda tidak pernah membaca siaran ini. Ferris mahu anda menggunakan peti ini?. Begini cara saya menambahkannya pada antara muka Wasm saya.
#[cfg(feature = "wasm")] mod wasm { use wasm_bindgen::prelude::wasm_bindgen; use crosscheck::{InterpreterTest, TreewalkAdapter}; // Export a function to JavaScript #[wasm_bindgen] pub fn greet() -> String { "Hello from WebAssembly!".to_string() } #[wasm_bindgen] pub fn evaluate(code: String) -> String { let result = TreewalkAdapter.execute(&code); format!("{}", result) } }
Jejak tindanan saya menunjukkan saya kepada punca saya: Saya menggunakan std::env untuk meminta beberapa sumber OS, yang tidak dibenarkan dalam masa jalan Wasm (iaitu bahagian kotak pasir). Saya meletakkan panggilan ini di belakang bendera ciri (ia berkaitan dengan cara saya menggodam-ily menentukan lokasi lib standard Python pada mesin hos) dan melancarkan binaan saya semula. Selepas beberapa kegagalan kecil yang berkaitan dengan memaparkan jenis pemulangan saya dengan betul….
IA BERFUNGSI. Inilah yang saya lihat sekarang dalam konsol penyemak imbas saya.
# wasm-pack helps compile our Rust code to WebAssembly and bundle it # with JavaScript bindings we can call from our HTML/JavaScript page. cargo install wasm-pack # wasm-pack also downloads the wasm32-unknown-unknown target via # rustup for us. If for whatever reason it does not, you can use this: # rustup target add wasm32-unknown-unknown # We must specify a feature flag because our wasm_bindgen interface is # behind the wasm feature flag. wasm-pack build --target web --out-dir wasm_ui/pkg -- --features wasm
tldr saya boleh menjalankan Python dalam penyemak imbas. (Untuk kredit mereka, RustPython melakukan ini juga: https://rustpython.github.io/demo/. Saya tidak melihat secara mendalam projek mereka tetapi nampaknya komprehensif.) Pemahaman senarai Python ditakrifkan dalam JavaScript dalam bentuk rentetan dan senarai respons dinilai oleh kod Rust yang disusun kepada Wasm dan ditukarkan semula kepada rentetan yang boleh dipaparkan oleh JavaScript.
Persediaan ini hanya menyokong ungkapan pada masa ini. Untuk menilai kenyataan (dan kemudian membaca kembali keputusannya), saya perlu mengekalkan keadaan di sebelah Rust. Saya juga bermimpi untuk membina REPL JavaScript. Itu kedengaran seperti masalah untuk masa depan-saya (dan impian yang membosankan tbh).
Saya telah bercakap cukup lama, jadi saya akan menangguhkan perbincangan Python terbenam sehingga Isnin depan.
Maaf atas umpan dan suis. Kalendar kandungan tidak menunggu sesiapa.
Untuk menjadi jelas, dengan Python terbenam, saya maksudkan membenamkan penterjemah CPython di dalam Memphis, bukan menjalankan Python dalam persekitaran "sistem terbenam". Itu akan menjadi sukar tanpa sebab. Tidak seperti Memphis, yang sukar untuk SERONOK.
Jika anda ingin mendapatkan lebih banyak siaran seperti ini terus ke peti masuk anda, anda boleh melanggan di sini!
Selain membimbing jurutera perisian, saya juga menulis tentang pengalaman saya sebagai orang autistik yang didiagnosis dewasa. Kurang kod dan bilangan jenaka yang sama.
Atas ialah kandungan terperinci Membina untuk WebAssembly. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!