程式語言 - GNU - C/C++ - 為何NanoPB Nest Message無法讀取到資料



參考資訊:
https://www.jianshu.com/p/cad578f48e0a
https://github.com/nanopb/nanopb/tree/master
https://github.com/afiskon/cpp-protobuf-example/tree/master
https://stackoverflow.com/questions/47704968/protoc-command-not-found-linux
https://stackoverflow.com/questions/62707863/how-to-encode-messages-with-map-using-google-protobuf-in-javascript-protocol

main.proto

syntax = "proto3";
  
message test {
    _opt opt  = 1;

    message _opt {
        string v1 = 1;
    }
}

main.options

test._opt.v1 max_size:255

main.c

#include <stdio.h>
#include <pb_encode.h>
#include <pb_decode.h>
   
#include "main.pb.h"
   
int main(int argc, char **argv)
{
    char buf[255] = {0};
       
    test org = test_init_zero;
    strcpy(org.opt.v1, "t1");
    pb_ostream_t os1 = pb_ostream_from_buffer(buf, sizeof(buf));
    pb_encode(&os1, test_fields, &org);
   
    test out = test_init_zero;
    pb_istream_t is2 = pb_istream_from_buffer(buf, os1.bytes_written);
    pb_decode(&is2, test_fields, &out);
   
    printf("opt.v1: %s\n", out.opt.v1);
    return 0;
}

編譯、執行

$ protoc --nanopb_out=-v:. main.proto
$ gcc main.c -o test main.pb.c -I. -lprotobuf-nanopb
$ ./test
    opt.v1:

out.opt.v1的結果並非預期是"t1"字串,原因在於Proto3預設都是使用Optional而非Required,因此,在做pb_encode()時,必須設定Field成True,如下修改後的程式

main.c

#include <stdio.h>
#include <pb_encode.h>
#include <pb_decode.h>
   
#include "main.pb.h"
   
int main(int argc, char **argv)
{
    char buf[255] = {0};
       
    test org = test_init_zero;
    org.has_opt = true;
    strcpy(org.opt.v1, "t1");
    pb_ostream_t os1 = pb_ostream_from_buffer(buf, sizeof(buf));
    pb_encode(&os1, test_fields, &org);
   
    test out = test_init_zero;
    pb_istream_t is2 = pb_istream_from_buffer(buf, os1.bytes_written);
    pb_decode(&is2, test_fields, &out);
   
    printf("opt.v1: %s\n", out.opt.v1);
    return 0;
}

測試

$ gcc main.c -o test main.pb.c -I. -lprotobuf-nanopb
$ ./test 
    opt.v1: t1

P.S. 感謝同事YUYU的協助,幫助司徒找到這個問題