Ayrıca bakınız: C++ sürümü: C++‘da enum’lar nasıl işlenir
NanoPB, gömülü sistemler için kod boyutu açısından optimize edilmiş bir Protocol Buffers uygulamasıdır. Bu yazı, NanoPB ile C’de enum tiplerinin nasıl işleneceğini gösterir.
Proto tanımı
Önce enum’lar içeren bir .proto dosyası oluşturun:
syntax = "proto3";
package example;
enum Status {
UNKNOWN = 0;
OK = 1;
ERROR = 2;
BUSY = 3;
}
message EnumMessage {
Status status = 1;
}NanoPB kodu oluşturma
NanoPB kodunu oluşturun:
protoc --nanopb_out=. enums.protoBu, enums.pb.h ve enums.pb.c dosyalarını oluşturur.
C örneği
Enum’ları işleyen tam bir C örneği:
#include <stdio.h>
#include <stdint.h>
#include "enums.pb.h"
#include "pb_encode.h"
#include "pb_decode.h"
// Enum'u stringe dönüştüren yardımcı fonksiyon
const char* status_to_string(example_Status status) {
switch (status) {
case example_Status_UNKNOWN: return "UNKNOWN";
case example_Status_OK: return "OK";
case example_Status_ERROR: return "ERROR";
case example_Status_BUSY: return "BUSY";
default: return "INVALID";
}
}
int main() {
// Kodlanmış mesaj için arabellek
uint8_t buffer[64];
size_t message_length;
// --- KODLAMA ---
example_EnumMessage message = example_EnumMessage_init_zero;
// Enum değerini ayarla
message.status = example_Status_OK;
// Kodlama için akış oluştur
pb_ostream_t ostream = pb_ostream_from_buffer(buffer, sizeof(buffer));
// Mesajı kodla
if (!pb_encode(&ostream, example_EnumMessage_fields, &message)) {
printf("Encoding failed: %s\n", PB_GET_ERROR(&ostream));
return 1;
}
message_length = ostream.bytes_written;
printf("Encoded %zu bytes\n", message_length);
// Kodlanmış verinin hex dökümünü yazdır
printf("Encoded data: ");
for (size_t i = 0; i < message_length; i++) {
printf("%02x ", buffer[i]);
}
printf("\n");
// --- KOD ÇÖZME ---
example_EnumMessage decoded = example_EnumMessage_init_zero;
// Kod çözme için akış oluştur
pb_istream_t istream = pb_istream_from_buffer(buffer, message_length);
// Mesajın kodunu çöz
if (!pb_decode(&istream, example_EnumMessage_fields, &decoded)) {
printf("Decoding failed: %s\n", PB_GET_ERROR(&istream));
return 1;
}
// Kodu çözülen değeri yazdır
printf("Decoded value:\n");
printf(" status: %s (enum value: %d)\n",
status_to_string(decoded.status), (int)decoded.status);
return 0;
}Derleme komutu
Örneği nanopb ile derleyin. NanoPB genellikle kaynak dosyaları doğrudan projenize dahil edilerek kullanılır:
gcc -o enums_example enums_example.c enums.pb.c pb_common.c pb_encode.c pb_decode.c -I.Not: NanoPB kaynak dosyaları (pb_common.c, pb_encode.c, pb_decode.c) projenizle birlikte doğrudan derlenmelidir. Bunları NanoPB GitHub deposundan edinebilirsiniz.
Python test betiği
Kodlamayı doğrulamak için Python’un protobuf kütüphanesini kullanabilirsiniz:
import enums_pb2
# İkili veriyi oku
with open('encoded.bin', 'rb') as f:
data = f.read()
# Kod çöz
msg = enums_pb2.EnumMessage()
msg.ParseFromString(data)
print("Python decoded values:")
print(f" status: {enums_pb2.Status.Name(msg.status)}")Önce Python protobuf tanımlarını derleyin:
protoc --python_out=. enums.protoArdından C örneğini, kodlanmış veriyi bir dosyaya kaydedecek şekilde değiştirin:
// Kodlamadan sonra bunu ekleyin:
FILE *f = fopen("encoded.bin", "wb");
fwrite(buffer, 1, message_length, f);
fclose(f);Switch ifadesinde enum örneği
Enum’ların switch ifadelerinde nasıl kullanılacağını gösteren bir örnek:
#include <stdio.h>
#include <stdint.h>
#include "enums.pb.h"
#include "pb_encode.h"
#include "pb_decode.h"
void handle_status(example_Status status) {
printf("Handling status: ");
switch (status) {
case example_Status_UNKNOWN:
printf("UNKNOWN - Default state\n");
break;
case example_Status_OK:
printf("OK - Operation successful\n");
break;
case example_Status_ERROR:
printf("ERROR - Operation failed\n");
break;
case example_Status_BUSY:
printf("BUSY - System busy\n");
break;
default:
printf("INVALID - Unknown enum value\n");
break;
}
}
int main() {
uint8_t buffer[64];
size_t message_length;
// Tüm enum değerlerini test et
example_Status test_values[] = {
example_Status_UNKNOWN,
example_Status_OK,
example_Status_ERROR,
example_Status_BUSY
};
for (size_t i = 0; i < 4; i++) {
example_EnumMessage message = example_EnumMessage_init_zero;
message.status = test_values[i];
pb_ostream_t ostream = pb_ostream_from_buffer(buffer, sizeof(buffer));
if (!pb_encode(&ostream, example_EnumMessage_fields, &message)) {
printf("Encoding failed: %s\n", PB_GET_ERROR(&ostream));
return 1;
}
message_length = ostream.bytes_written;
example_EnumMessage decoded = example_EnumMessage_init_zero;
pb_istream_t istream = pb_istream_from_buffer(buffer, message_length);
if (!pb_decode(&istream, example_EnumMessage_fields, &decoded)) {
printf("Decoding failed: %s\n", PB_GET_ERROR(&istream));
return 1;
}
handle_status(decoded.status);
}
return 0;
}Önemli noktalar
- Enum tanımı:
.protodosyasında açık değerlerle enum’lar tanımlayın - Oluşturulan tipler: NanoPB,
package_EnumNameadlandırmasıyla enum tipleri oluşturur - Kodlama: Enum değerini doğrudan alana atayın
- Kod çözme: Enum değerleri otomatik olarak çözülür
- Varsayılan değerler: İlk enum değeri (genellikle 0) varsayılandır
- Switch ifadeleri: Enum’lar switch ifadelerinde doğal olarak çalışır
- Tip güvenliği: Enum’lar ham tamsayılara göre tip güvenliği sağlar
- Bilinmeyen değerler: Geçersiz enum değerleri sayısal değerleri olarak çözülebilir
Enum’lar ne zaman kullanılır
- Sabit bir olası değer kümesine sahip olduğunuzda
- Durum veya mod alanları için tip güvenliği istediğinizde
- Kendi kendini belgeleyen kod istediğinizde
- Farklı çalışma modlarını ayırt etmeniz gerektiğinde
- Mesajlara anlamsal anlam kodlamak istediğinizde
Beklenen çıktı
Encoded 2 bytes
Encoded data: 08 01
Decoded value:
status: OK (enum value: 1)Beklenen çıktı (switch örneği)
Handling status: UNKNOWN - Default state
Handling status: OK - Operation successful
Handling status: ERROR - Operation failed
Handling status: BUSY - System busyC++‘dan farkları
C sürümü, C++ sürümüyle neredeyse aynıdır:
- Enum’lar hem C hem de C++‘da aynı şekilde çalışır
- C’de printf format belirteçleri için açık cast kullanın
- Enum işleme için C++‘a özgü özellikler gerekmez
- Oluşturulan kod her iki dil için de aynıdır
Diğer NanoPB yazıları
- C++‘da temel skaler tipler
- C’de temel skaler tipler
- C++‘da string tipleri
- C’de string tipleri
- C++‘da bytes tipleri
- C’de bytes tipleri
- C++‘da opsiyonel alanlar
- C’de opsiyonel alanlar
- C++‘da tekrarlanan alanlar/diziler
- C’de tekrarlanan alanlar/diziler
- C++‘da enum’lar
- C++‘da iç içe mesajlar
- C’de iç içe mesajlar
- C++‘da Oneof/union tipleri
- C’de Oneof/union tipleri
- C++‘da özel dizi dönüştürücüler
- C’de özel dizi dönüştürücüler