Protobuf چیست؟
فرض کنید میخواهیم بین دو سیستم -مثلا 2 میکروکنترلرمتفاوت یا میکروکنترلر و کامپیوتر– دیتای یک struct را به اشتراک بگذاریم. برای اینکار نهایتا باید یک رشته بایت مابین این دو سیستم تبادل شود. اما برای تبدیل struct به یک رشته بایت قابل انتقال چه راهی داریم؟
ابتدا فرض کنیم که نام struct ما در فرستنده my_struct_t است و متغیری که در برنامه از آن ایجاد کرده و میخواهیم انتقال دهیم my_struct_var نام دارد.
یکی از راهها این است که در گیرنده هم my_struct_t را مثل فرستنده تعریف کنیم. سپس از آدرس my_struct_var به اندازهی سایز آن -sizeof(my_struct_t)- شروع به فرستادن بایت به بایت این متغیر struct کنیم. در گیرنده هم پس از ذخیره اطلاعات دریافتی در حافظه، آدرس شروع این اطلاعات را برابر با اشارهگری به struct تعریف شده -* my_struct_t- کنیم. راه حل ساده و قشنگی به نظر میرسد و همه چیز خوب است، جز اینکه ممکن است مشاهده کنید مقادیر struct فرستنده و گیرنده یکی نیستند!
این اتفاق میتواند ناشی از تفاوت در endianness، padding و یا سایز متفاوت در data typeهای پایه مثل int و double در سیستم مبدا و مقصد باشد.
به جز این مشکل نه چندان کوچک، این را هم باید در نظر داشت که شاید زبان برنامهنویسی متفاوتی در مبدا و مقصد داشته باشیم و نتوان structای مشابه مبدا در مقصد ایجاد کرد.
اما راه مناسب چیست؟
راه مناسب serialization دیتا است. در دنیای کامپیوتر به پروسهی تبدیل یک data structure یا object به یک رشته بایت به جهت ذخیره یا ارسال serialization میگویند. برای اینکار هم راههای مختلفی هست. در اینجا پیشنهاد من استفاده از google protobuf هست که علاوه بر پوشش اشکالات بالا به ما امکانات بیشتری مثل فرستادن داده به صورت optional هم میدهد.
متاسفانه google protobuf به صورت پیش فرض از زبان C پشتیبانی نمیکند. اما خبر خوب این هست که ما میتوانیم از کتابخانه pbnano استفاده کنیم که بر اساس google protobuf و برای زبان C توسعه داده شده.