مجرد التفاف كيو تي آخر ل gRPC و protobuf



منذ وقت ليس ببعيد ، كنت في حيرة من حقيقة أنه لا يوجد ما يكفي من الأغلفة والمولدات سهلة وبسيطة ل protobuf و gRPC ، القائمة ومتوافقة تماما مع كيو تي. جئت عبر المقالات ، بما في ذلك هنا حول الأغلفة ، لكن استخدامها بدا لي أقل عملية من واجهة برمجة تطبيقات C ++ الحالية.

قليلا عن gRPC و protobuf


لنقم بمحاكاة الموقف: ستقوم بكتابة مشروع متعدد الأنظمة وتحتاج إلى اختيار إطار عمل RPC للتواصل مع خدماتك. يمكنك دائمًا أن تثقب في الصندوق وتقول "أنا الإطار الخاص بي" ، لكن يبدو لي أننا نعيش في عصر من الحلول الجاهزة. تم تقديم أحد هذه الحلول لنا من قبل شركة معروفة لفترة طويلة. لا أفترض مقارنة أطر عمل RPC ، هذا ليس الغرض من هذه المقالة. فقط لسرد ما يعجبني في gRPC:

  • موجزة وواضحة IDL
  • وجود عدد كبير من المولدات لمختلف المنصات
  • رمز عميل / خادم تم إنشاؤه لتطبيقات اختبار النماذج الأولية السريعة والسهلة

الى هذه النقطة


نظرًا لحقيقة أن Qt تعمل بشكل جيد مع انعكاس الكتابة ، وكمية المعلومات الوصفية عمومًا على أعلى مستوى ، فقد أدركت أنك بحاجة إلى مولدك الخاص الذي سينشئ رمز Qt "خالص" ، دون تداخل مكتبات الطرف الثالث. لذلك ولدت qtprotobufgen.

qtprotobufgen


qtprotobufgen هو أبسط مولد بطبيعته ، والذي يعتمد على واجهة برمجة التطبيقات المقدمة من libprotoc. إذا كنت ترغب في عمل شيء من هذا القبيل لاحتياجاتك ، سأترك القليل من الغش.

  • لديك نقطة دخول واحدة إلى فئة البرنامج المساعد :: google :: protobuf :: compiler :: CodeGenerator ، والتي تحتاج إلى وراثة منها
  • إنشاء طريقة افتراضية يحدد التوليد عند العمل مع ملف .proto منفصل
  • تحدد طريقة GenerateAll الافتراضية التوليد عند العمل مع مجموعة كاملة من ملفات .proto المقدمة للجيل أو تكون تبعيات
  • طريقة HasGenerateAll الافتراضية هي في الأساس بقايا باقية من الإصدارات السابقة. عودة صحيح

يجب أن أقول على الفور أنه لا توجد رغبة في كتابة محلل / مولد خاص بي من الصفر ، لأن هناك حلًا جاهزًا من مطوري protobuf. ولكن إذا كنت ترغب في ذلك ، يمكنك قراءة الدفق الثنائي الذي يصدره protoc ، أو كتابة محلل ملف proto الخاص بك.

أثناء التطوير ، ظهر عيب كبير للمولد المكتوب باللغة المترجمة: كان من الصعب وضع التوليد والتجميع في مكدس CMake واحد. نظرًا لأن Qt يقوم بإنشاء معلومات كائن التعريف ، استنادًا إلى ملفات الرأس التي تحتوي على ماكرو Q_OBJECT في نص الفئات المعلنة في ملف الرأس ، فمن الضروري في مرحلة التكوين (قراءة cmake) أن يكون لديك فكرة عن الملفات التي سيوفرها moc لإنشاء المزيد من التعليمات البرمجية. كحل ، اضطررت إلى اللجوء إلى لغة التفسير Go (Lang) ، التي لم تخلق تبعيات إضافية وقمت بعملها بشكل مثالي ، لكنها لم تجر اختبارات كافية.

يخضع المولد لقواعد protoc الحالية ، وفي وقت كتابة هذا التقرير ، لا يقدم أي خيارات توليد إضافية:

protoc --plugin=protoc-gen-qtprotobuf=<path/to/bin>/qtprotobufgen --qtprotobuf_out=<output_dir> <protofile>.proto [--qtprotobuf_opt=out=<output_dir>] 

من أجل البساطة وسهولة الاستخدام ، يمكنك استخدام إجراءات cmake المعدة خصيصًا لإنشاء التعليمات البرمجية ، ودمجها في مشروع cmake. مزيد من التفاصيل ...

عن المكتبات


لا أرى فائدة كبيرة في وصف واجهة برمجة التطبيقات بالتفصيل. يمكن لأولئك الذين يرغبون في إنشاء الوثائق وقراءة المزيد حول واجهة برمجة التطبيقات المتاحة حاليًا.

وينقسم المشروع إلى 2 أجزاء منطقية qtprotobuf و qtgrpc. من الأسماء ، أعتقد أن الغرض من كل مكون واضح. لقد حاولنا جعل الاستخدام مناسبًا قدر الإمكان ، نظرًا لوجود خيارات تكامل لكل من المكتبة التي تم تجميعها مسبقًا وتثبيتها في النظام ، ودمج المشروع الفرعي في مشروع cmake الخاص بك.

يتم تصدير الشفرة التي تم إنشاؤها بالكامل * إلى QML ، مما يجعل العمل مع واجهة برمجة تطبيقات gRPC أسهل بكثير.

استخدام


بعد الدمج مع المشروع وأداء الجيل ، ستتلقى مجموعة من الملفات المصدر ، والتي سيتم جمعها لاحقًا في مكتبة ثابتة وترتبط بالملف الثنائي. استبعدت التغييرات الحديثة إمكانية التسجيل الثابت للأنواع المولدة والأنواع الأولية. لذلك ، تحتاج إلى رعاية تسجيلهم في المشروع:

 ... #include <QtProtobufTypes> ... int main(int argc, char *argv[]) { QtProtobuf::registerProtoTypes(); ... //   Qt  } 

في وقت كتابة هذا التقرير ، لا توجد طريقة واحدة لتسجيل جميع الأنواع التي تم إنشاؤها لحزمة proto ، لذلك تحتاج إلى استدعاء طريقة qRegisterProtobufType لجميع الأنواع المستخدمة في التطبيق:

 ... qRegisterProtobufType<MyProtoType>(); ... 

تم وصف استخدام المكتبات والمولد في README ، وهناك مثالان يرافقان المشروع. بالنسبة لأولئك الذين ليسوا على دراية gRPC / protobuf أقترح أن تقرأ الوثائق الرسمية

للمطورين


لقد حاولنا الالتزام بـ TDD أثناء التطوير ، ولا نريد الخروج عنه. كما أوضحت تجربتنا ، فإن TDD يوفر لك عند إعادة إنشاء أو تحديث واجهة برمجة التطبيقات ، فهو يساعد على اكتشاف المشكلات الخفية. لذلك ، إذا كانت هناك رغبة في المساهمة ، فاستعد لكتابة الوحدات والوحدات والاختبارات الوظيفية.

* المشكلات المعروفة


يوجد حاليًا عدد من المشكلات المتعلقة بـ Qt. تم حل بعضها ، بمشاركتنا أو بدون مشاركتنا ، ولكن لم يتم تضمينها جميعًا في إصدارات Qt الحالية. السبب الرئيسي هو عدم إمكانية الوصول إلى بعض أنواع protobuf الأساسية من كود qml. أعتقد أنه ليس سراً على أي شخص أن مجموعة الأنواع المتوفرة في QML محدودة للغاية ، ويعزى ذلك جزئيًا إلى استخدام V8 كمحرك JS. أخفقت محاولة لجعل QML أكثر ملاءمةً للأنواع المخصصة (على سبيل المثال ، fix32 ، sint32) ، لكنها تحولت إلى حل مصدر المشكلة . يحتوي التنفيذ الحالي لـ QtNetwork أيضًا على عدد من المشكلات ، لكن فريق Qt يعمل على حلها بسرعة.
QTBUG-77852
QTBUG-76303
QTBUG-78310

خطط


ترتبط جميع الأنشطة الحالية باستكشاف الأخطاء وإصلاحها في رمز المشروع أو في رمز Qt. ولكن هناك قدر كبير من العمل المرتبط بالوظائف الجديدة:

  1. الانتقال إلى زوج واحد من ملفات .h / .cpp للرمز الذي تم إنشاؤه
  2. تنفيذ خادم GRPC
  3. إعادة تدوير API لبيانات اعتماد gRPC
  4. توزيع الكود الذي تم إنشاؤه في الدلائل وإنشاء مكونات إضافية للمشروع الفرعي للتحميل المنفصل للحزم والوحدات التي تم إنشاؤها
  5. التكامل Qmake
  6. تنفيذ CI

هناك بعض الأعمال المتراكمة ، والتي لا تزال مخزنة في مستودع المشروع الخاص بها.

بدلاً من الاستنتاج ، أود أن أقول شكراً للرفاق من PVS-Studio على المفتاح المقدم لمشاريع OSS. بمساعدتهم ، وجدوا خللًا مهمًا في الشفرة التي تم إنشاؤها.

قم بتنزيل ، راجع المشروع واللعب مع الأمثلة هنا .

Source: https://habr.com/ru/post/ar467893/


All Articles