
Belum lama ini, saya bingung dengan kenyataan bahwa tidak ada cukup pembungkus dan generator yang nyaman dan sederhana untuk protobuf dan gRPC, berbasis dan sepenuhnya kompatibel dengan Qt. Saya menemukan artikel, termasuk di sini tentang pembungkus, tetapi penggunaannya bagi saya jauh kurang praktis daripada bahkan C ++ API yang ada.
Sedikit tentang gRPC dan protobuf
Mari kita simulasikan sebuah situasi: Anda akan menulis proyek multi-platform dan Anda perlu memilih kerangka kerja RPC untuk berkomunikasi dengan layanan Anda. Anda selalu dapat meninju dada Anda dan mengatakan "Saya adalah kerangka kerja saya sendiri," tetapi bagi saya sepertinya kita hidup di era solusi siap pakai. Salah satu solusi semacam itu dipresentasikan kepada kami oleh perusahaan terkenal untuk waktu yang lama. Saya tidak berasumsi untuk membandingkan kerangka kerja RPC, ini bukan tujuan dari artikel ini. Cukup untuk daftar apa yang saya suka tentang gRPC:
- IDL ringkas dan jelas
- Kehadiran sejumlah besar generator untuk berbagai platform
- Kode klien / server yang dihasilkan untuk pembuatan prototipe dan penulisan aplikasi pengujian yang cepat dan mudah
Ke intinya
Karena fakta bahwa Qt melakukan dengan cukup baik dengan jenis refleksi, dan jumlah meta-informasi umumnya pada tingkat tertinggi, itu sampai pada kesadaran bahwa Anda memerlukan generator Anda sendiri yang akan menghasilkan kode Qt "murni", tanpa menyelingi perpustakaan pihak ketiga. Jadi qtprotobufgen lahir.
qtprotobufgen
qtprotobufgen adalah generator inheren yang paling sederhana, yang didasarkan pada API yang disediakan oleh libprotoc. Jika Anda ingin membuat sesuatu seperti itu untuk kebutuhan Anda, saya akan meninggalkan sedikit kecurangan.
- Anda memiliki satu titik masuk ke kelas plugin :: google :: protobuf :: compiler :: CodeGenerator, dari mana Anda perlu mewarisi
- Menghasilkan metode virtual menentukan pembuatan ketika bekerja dengan file .proto terpisah
- Metode virtual GenerateAll menentukan pembuatan ketika bekerja dengan array penuh file .proto yang disediakan untuk pembuatan atau menjadi dependensi
- Metode HasGenerateAll virtual pada dasarnya adalah peninggalan yang bertahan dari versi sebelumnya. Kembali benar
Saya harus segera mengatakan bahwa tidak ada keinginan untuk menulis parser / generator saya sendiri dari awal, karena ada solusi siap pakai dari pengembang protobuf. Tetapi jika Anda mau, Anda bisa membaca aliran biner yang memproteksi masalah, atau menulis parser file proto Anda sendiri.
Selama pengembangan, satu kelemahan signifikan dari generator yang ditulis dalam bahasa yang dikompilasi muncul: sulit untuk menempatkan generasi dan kompilasi dalam satu tumpukan CMake. Karena fakta bahwa Qt menghasilkan informasi meta-objek, berdasarkan file header yang memiliki makro Q_OBJECT di dalam tubuh kelas yang dinyatakan dalam file header, perlu pada tahap konfigurasi (baca cmake) untuk memiliki gambaran tentang file yang akan disediakan oleh moc untuk pembuatan kode lebih lanjut. Sebagai solusi, saya harus menggunakan bahasa yang ditafsirkan Go (Lang), yang tidak menciptakan dependensi tambahan dan melakukan tugasnya dengan sempurna, tetapi tidak lulus pengujian yang cukup.
Generator tunduk pada aturan protoc yang ada, dan pada saat penulisan, tidak memperkenalkan opsi generasi tambahan apa pun:
protoc --plugin=protoc-gen-qtprotobuf=<path/to/bin>/qtprotobufgen --qtprotobuf_out=<output_dir> <protofile>.proto [--qtprotobuf_opt=out=<output_dir>]
Untuk kesederhanaan dan kemudahan penggunaan, Anda dapat menggunakan rutin cmake yang disiapkan khusus untuk menghasilkan kode, dan menanamkannya dalam proyek cmake.
Lebih detail ...Tentang Perpustakaan
Saya tidak melihat banyak gunanya dalam menggambarkan API secara rinci. Mereka yang ingin dapat
menghasilkan dokumentasi dan membaca lebih banyak tentang API yang saat ini tersedia.
Proyek ini dibagi menjadi 2 bagian logis qtprotobuf dan qtgrpc. Dari namanya, saya pikir tujuan masing-masing komponen jelas. Kami mencoba membuat penggunaan senyaman mungkin, karena ada opsi integrasi dengan pustaka yang dirakit sebelumnya dan diinstal dalam sistem, dan integrasi subproyek ke dalam proyek cmake Anda.
Kode yang dihasilkan sepenuhnya
* diekspor ke QML, yang membuat bekerja dengan API gRPC jauh lebih mudah.
Gunakan
Setelah berintegrasi dengan proyek dan melakukan pembuatan, Anda akan menerima satu set file sumber, yang nantinya akan dikumpulkan di perpustakaan statis dan ditautkan ke file biner Anda. Perubahan terbaru mengecualikan kemungkinan pendaftaran statis yang dihasilkan dan tipe proto. Karena itu, Anda perlu mengurus pendaftaran mereka di proyek:
... #include <QtProtobufTypes> ... int main(int argc, char *argv[]) { QtProtobuf::registerProtoTypes(); ... // Qt }
Pada saat penulisan, tidak ada metode tunggal untuk mendaftarkan semua jenis yang dihasilkan untuk paket proto, jadi Anda perlu memanggil metode qRegisterProtobufType untuk semua jenis yang digunakan dalam aplikasi:
... qRegisterProtobufType<MyProtoType>(); ...
Penggunaan perpustakaan dan generator dijelaskan dalam README, dan beberapa contoh menyertai proyek. Bagi mereka yang sama sekali tidak akrab dengan gRPC / protobuf saya sarankan Anda membaca
dokumentasi resmiUntuk pengembang
Kami mencoba mematuhi TDD selama pengembangan, dan tidak ingin menyimpang darinya. Seperti yang ditunjukkan oleh pengalaman kami, TDD menyelamatkan Anda saat refactoring atau memperbarui API, itu membantu mendeteksi masalah tersembunyi. Karena itu, jika ada keinginan untuk berkontribusi, bersiaplah untuk menulis unit, unit dan tes fungsional.
* Masalah yang diketahui
Saat ini ada sejumlah masalah terkait Qt. Beberapa dari mereka diselesaikan, dengan kami atau tanpa partisipasi kami, tetapi tidak semuanya dimasukkan dalam rilis Qt saat ini. Yang utama adalah tidak dapat diaksesnya beberapa jenis protobuf dasar dari kode qml. Saya pikir bukan rahasia bagi siapa pun bahwa rangkaian tipe yang tersedia di QML sangat terbatas, sebagian karena penggunaan V8 sebagai mesin JS. Upaya untuk membuat QML sedikit lebih ramah untuk tipe yang dikustomisasi (misalnya, fixed32, sint32) gagal, tetapi ternyata memperbaiki sumber
masalah . Implementasi QtNetwork saat ini juga memiliki sejumlah masalah, tetapi tim Qt segera memperbaikinya.
QTBUG-77852QTBUG-76303QTBUG-78310Paket
Semua aktivitas saat ini terkait dengan pemecahan masalah dalam kode proyek atau dalam kode Qt. Tetapi ada sejumlah besar pekerjaan yang terkait dengan fungsi baru:
Transisi ke sepasang file .h / .cpp untuk kode yang dihasilkan- Implementasi server GRPC
Daur ulang API untuk kredensial gRPC- Distribusi kode yang dihasilkan ke direktori dan pembuatan plug-in sub-proyek untuk pemuatan paket dan modul yang dihasilkan secara terpisah
Integrasi QmakeImplementasi CI
Ada beberapa simpanan, yang masih disimpan di repositori proyeknya sendiri.
Alih-alih kesimpulan, saya ingin mengucapkan terima kasih kepada kawan-kawan dari PVS-Studio untuk kunci yang disediakan untuk proyek OSS. Dengan bantuan mereka, mereka menemukan bug yang agak kritis dalam kode yang dihasilkan.
Unduh, lihat proyeknya dan mainkan dengan contoh di
sini .