Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Кто работал с Google Protocol Buffers ? Есть вопрос ! / 25 сообщений из 31, страница 1 из 2
08.10.2020, 11:11
    #40006497
defecator
Модератор форума
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кто работал с Google Protocol Buffers ? Есть вопрос !
Больше двух лет пользуюсь вот этой замечательной библиотекой для Delphi:
https://blog.grijjy.com/2017/04/25/binary-serialization-with-google-protocol-buffers/

Всё было замечательно, до позавчерашнего дня.

Суть в чём.

Пишу прошивку (на проклятых сях) под контроллер STM32F767, который должен общаться через TCP/IP с софтиной,
писанной на Delphi с использованием вышеупомянутой библиотеки.

Для реализации PB под эти ваши Си есть офигенная библиотека nanoPB, её и использую:
https://jpa.kapsi.fi/nanopb/

Описание тестового .proto:

авторsyntax = "proto2";

message Example {
required int32 value = 1;
}

компилятор .proto в сишный заголовок выдаёт на выходе (только часть показываю):
Код: plaintext
1.
2.
3.
4.
/* Struct definitions */
typedef struct _Example {
    int32_t value;
} Example;



в поле value я передаю через PB значение 540, на выходе получаю закодированное значение 089C04
онлайн-декодер правильно его декодирует в значение 540 и тип поля - varint

Теперь переходим к дельфовой части

описание структуры:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
type
    TMess = record
    public
      [Serialize(1)] value : LongInt ; 
    public
      procedure Initialize ;
    end ;

var
   InArr : TBytes ;
   Rec : TMess ;
begin
     InArr := [$08, $9C, $04] ;
     TgoProtocolBuffer.Deserialize(TypeInfo(TMess), Rec, @InArr[0], Length(InArr)) ;
end ;



На выходе получаем 270, а не 540, то есть ровно половину
Если я в nanoPB закодирую любое значение, 2020, например, то дельфовый десериализатор все равно покажет ровно в два раза меньшее значение.

Методом глубокого научного тыка я нашёл вариант,
когда дельфя раскодирует правильно - в описании структуры TMess надо заменить тип Integer на LongWord или DWord,
то есть

Код: pascal
1.
2.
3.
4.
5.
6.
7.
type
    TMess = record
    public
      [Serialize(1)] value : LongWord ; (* Integer - не работает почему-то *)
    public
      procedure Initialize ;
    end ;


Тогда значение будет возвращаться нормально, ровно так, как его передаёт сишная часть

Провёл эксперимент уже на самой дельфовой библиотеке - закодировал через неё значение 540

вариант
Код: pascal
1.
value : LongWord ;


даёт на выходе правильное значение - 089C04

а вариант
Код: pascal
1.
value : LongInt ;


даёт на выходе значение 08B808, которое онлайн-декодер трактует как 1080, то есть удвоенное значение - 540 * 2 = 1080

В итоге (для типа LongInt) получается следующее.
NanoPB(вход 540) -> 089C04 -> Delphi(выход 270) = уполовиненное значение 540
Delphi(вход 540) -> 08B808 -> nanoPB(выход 1080) = удвоенное значение 540

В общем, вопрос в следующем - чего я не замечаю ?
...
Рейтинг: 0 / 0
08.10.2020, 11:47
    #40006518
iStrannik
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кто работал с Google Protocol Buffers ? Есть вопрос !
Может в порядке байт дело?
На STM32 порядок байт MSB,LSB(ARM), а на Delphi(x86) LSB,MSB нужно делать Value := Swap(Value);
...
Рейтинг: 0 / 0
08.10.2020, 12:01
    #40006530
defecator
Модератор форума
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кто работал с Google Protocol Buffers ? Есть вопрос !
iStrannik
Может в порядке байт дело?
На STM32 порядок байт MSB,LSB(ARM), а на Delphi(x86) LSB,MSB нужно делать Value := Swap(Value);


PB кросс-платформенный, это не требуется в явном виде
...
Рейтинг: 0 / 0
08.10.2020, 13:21
    #40006558
Mixrud
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кто работал с Google Protocol Buffers ? Есть вопрос !
Longint это платформозависимый тип.
LongWord (DWord) платформонезависимый тип
...
Рейтинг: 0 / 0
08.10.2020, 13:23
    #40006560
Гаджимурадов Рустам
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кто работал с Google Protocol Buffers ? Есть вопрос !
defecator> В общем, вопрос в следующем - чего я не замечаю ?

Для 0032 вместо 270 что получается?

LongWord и LongInt имеют одну разрядность, там
не в бобине дело, скорее всего, побитово смотри.

Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
08.10.2020, 13:46
    #40006575
Kazantsev Alexey
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кто работал с Google Protocol Buffers ? Есть вопрос !
Mixrud
Longint это платформозависимый тип.
LongWord (DWord) платформонезависимый тип

Они оба платформозависимые: http://docwiki.embarcadero.com/RADStudio/Rio/en/Simple_Types_(Delphi)#Platform-Dependent_Integer_Types
...
Рейтинг: 0 / 0
08.10.2020, 13:55
    #40006576
Соколинский Борис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кто работал с Google Protocol Buffers ? Есть вопрос !
defecator
В общем, вопрос в следующем - чего я не замечаю ?
Может там где-то используется сдвиг разрядов с учетом знака (SAR/SAL)?
...
Рейтинг: 0 / 0
08.10.2020, 14:05
    #40006579
defecator
Модератор форума
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кто работал с Google Protocol Buffers ? Есть вопрос !
Гаджимурадов Рустам
defecator> В общем, вопрос в следующем - чего я не замечаю ?

Для 0032 вместо 270 что получается?


для LongInt:
nanoPB(32) -> 0820 -> Delphi(16)
Delphi(32) -> 0840 -> nanoPB(64)

сдвиг на один бит

Есть подозрение на то, что LongInt имеет знак, а LongWord его не имеет.

дельфовая библиотека для PB получает информацию о полях записи через RTTI,
возможно, тут где-то и порылась собака
...
Рейтинг: 0 / 0
08.10.2020, 14:12
    #40006584
zedxxx
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кто работал с Google Protocol Buffers ? Есть вопрос !
defecator(* Integer - не работает почему-то *)
Отсюда и надо плясать. Почему не работает Integer? Явно смахивает на баг библиотеки.
...
Рейтинг: 0 / 0
08.10.2020, 14:15
    #40006586
Zelius
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кто работал с Google Protocol Buffers ? Есть вопрос !
defecator,

не работал, но может в этом?
авторThe integer data types are stored in an efficient “VarInt” format. This means that smaller values are stored in less bytes than larger values. 32-bit integer types are stored in 1-5 bytes, and 64-bit integer types are stored in 1-10 bytes. Sometimes, you can have integer data that contains random values across the entire 32-bit or 64-bit range. Common examples of these are CRC or Hash values and time stamps. In those cases, it is more efficient to store these integers as fixed 32-bit or 64-bit values. You can do this by declaring the field as one of 4 fixed integer types:

FixedInt32, FixedUInt32
FixedInt64, FixedUInt64

FixedInt32 - попробуй
...
Рейтинг: 0 / 0
08.10.2020, 14:49
    #40006595
Гаджимурадов Рустам
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кто работал с Google Protocol Buffers ? Есть вопрос !
defecator> Есть подозрение на то, что LongInt имеет знак, а LongWord его не имеет.

Подозрение? Лонгворд - беззнаковый.
Перепроверь сишное обявление и код.


Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
08.10.2020, 15:19
    #40006605
defecator
Модератор форума
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кто работал с Google Protocol Buffers ? Есть вопрос !
Гаджимурадов Рустам
defecator> Есть подозрение на то, что LongInt имеет знак, а LongWord его не имеет.

Подозрение? Лонгворд - беззнаковый.
Перепроверь сишное обявление и код.


я имел ввиду, что разница только в этом

в сях объявлено int32, это 4-хбайтное знаковое, Longint (для x32) - тоже знаковый 4-хбайтный
...
Рейтинг: 0 / 0
08.10.2020, 16:12
    #40006617
defecator
Модератор форума
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кто работал с Google Protocol Buffers ? Есть вопрос !
Zelius
defecator,

не работал, но может в этом?
авторThe integer data types are stored in an efficient “VarInt” format. This means that smaller values are stored in less bytes than larger values. 32-bit integer types are stored in 1-5 bytes, and 64-bit integer types are stored in 1-10 bytes. Sometimes, you can have integer data that contains random values across the entire 32-bit or 64-bit range. Common examples of these are CRC or Hash values and time stamps. In those cases, it is more efficient to store these integers as fixed 32-bit or 64-bit values. You can do this by declaring the field as one of 4 fixed integer types:

FixedInt32, FixedUInt32
FixedInt64, FixedUInt64

FixedInt32 - попробуй

В этом случае в дельфийской библиотеке для значения 32 - 0D20000000
А с типом int32 в сишной библиотеке nanoPB сопоставить не с чем,
там только int32, bytes и string
...
Рейтинг: 0 / 0
09.10.2020, 07:05
    #40006791
Дегтярев Евгений
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кто работал с Google Protocol Buffers ? Есть вопрос !
defecator,

089c04 - верное значение в wire-формате для Example с value=540
08 - маркер поля (wire type 0, номер поля 1)
9c04 - закодированное в varint целое со знаком 540

В wire-формате типов значительно меньше чем в протофайле. Для кодирования целых используется 3 типа - varint, 32-bit, 64bit. Последние 2 для fixed типов (fixed64, sfixed64, fixed32, sfixed32). Остальные, ключая bool и enum, кодируются в varint. Тут есть нюанс, кодирование отличается для знаковых и беззнаковых типов. Для беззнаковых последователность бит для кодирования берется как есть, а для знаковых оно сначала преобразеется к беззнаковому, где положительное значение как раз удваивается ( https://developers.google.com/protocol-buffers/docs/encoding#types). Поэтому важно как закодированное цело интерпретируется на принимающие стороне как знаковое или беззнаковое.

По тому что ты пишешь, получается что значение декодируется как беззнаковое. Ошибка однозначно на принимающей стороне. Но где ошибка, в самой либе или в ее использовании, я хз.
...
Рейтинг: 0 / 0
09.10.2020, 13:10
    #40006906
defecator
Модератор форума
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кто работал с Google Protocol Buffers ? Есть вопрос !
Дегтярев Евгений
defecator,

089c04 - верное значение в wire-формате для Example с value=540
08 - маркер поля (wire type 0, номер поля 1)
9c04 - закодированное в varint целое со знаком 540

В wire-формате типов значительно меньше чем в протофайле. Для кодирования целых используется 3 типа - varint, 32-bit, 64bit. Последние 2 для fixed типов (fixed64, sfixed64, fixed32, sfixed32). Остальные, ключая bool и enum, кодируются в varint. Тут есть нюанс, кодирование отличается для знаковых и беззнаковых типов. Для беззнаковых последователность бит для кодирования берется как есть, а для знаковых оно сначала преобразеется к беззнаковому, где положительное значение как раз удваивается ( (подозрительная ссылка!) https://developers.google.com/protocol-buffers/docs/encoding#types). Поэтому важно как закодированное цело интерпретируется на принимающие стороне как знаковое или беззнаковое.

По тому что ты пишешь, получается что значение декодируется как беззнаковое. Ошибка однозначно на принимающей стороне. Но где ошибка, в самой либе или в ее использовании, я хз.


На этот нюанс со знаковыми/беззнаковыми целочисленными я решил забить для ясности.
Вместо int32 на стороне nanoPB использую double - вот это однозначно и чётко ложится на тип Double в дельфи
И без всяких нюансов.
...
Рейтинг: 0 / 0
09.10.2020, 14:14
    #40006945
Дегтярев Евгений
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кто работал с Google Protocol Buffers ? Есть вопрос !
defecator,

> (подозрительная ссылка!)

почему ты посчитал ссылку подозрительной? ))
...
Рейтинг: 0 / 0
09.10.2020, 14:33
    #40006956
Гаджимурадов Рустам
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кто работал с Google Protocol Buffers ? Есть вопрос !
Дегтярев Евгений> почему ты посчитал ссылку подозрительной? ))

Это не он, а движок форума.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
09.10.2020, 14:37
    #40006959
Соколинский Борис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кто работал с Google Protocol Buffers ? Есть вопрос !
Дегтярев Евгений
почему ты посчитал ссылку подозрительной?
Это движок 22108475 , judge не поправил.
"Быстрый ответ" нужно включить, там этого бага нет.
...
Рейтинг: 0 / 0
09.10.2020, 16:43
    #40007021
Дегтярев Евгений
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кто работал с Google Protocol Buffers ? Есть вопрос !
Гаджимурадов Рустам
Это не он, а движок форума.

подозрительный какой
...
Рейтинг: 0 / 0
09.10.2020, 16:45
    #40007024
Дегтярев Евгений
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кто работал с Google Protocol Buffers ? Есть вопрос !
почему ТС выбрал именно протобаф, у которого для делфи нет офф либы?
...
Рейтинг: 0 / 0
09.10.2020, 17:20
    #40007032
rgreat
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кто работал с Google Protocol Buffers ? Есть вопрос !
...
Рейтинг: 0 / 0
09.10.2020, 17:22
    #40007034
rgreat
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кто работал с Google Protocol Buffers ? Есть вопрос !
Вообще этот самый протобаф не такой и сложный.
...
Рейтинг: 0 / 0
09.10.2020, 20:41
    #40007117
Дегтярев Евгений
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кто работал с Google Protocol Buffers ? Есть вопрос !

не увидел ссылок на него на странице протобафа отсюда и заявление про отсутствие официальной либы

зы
почему половина ссылок которые я тут вижу sourceforge.net ?
...
Рейтинг: 0 / 0
09.10.2020, 21:41
    #40007139
zedxxx
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кто работал с Google Protocol Buffers ? Есть вопрос !

Для него, кстати, и генератор есть: https://github.com/kami-soft/ProtoBufGenerator
...
Рейтинг: 0 / 0
10.10.2020, 15:28
    #40007250
defecator
Модератор форума
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Кто работал с Google Protocol Buffers ? Есть вопрос !
zedxxx

Для него, кстати, и генератор есть: https://github.com/kami-soft/ProtoBufGenerator


для библиотеки, которую я использую, и на которую ссылка в первом посте,
https://blog.grijjy.com/2017/04/25/binary-serialization-with-google-protocol-buffers/
никакой генератор не нужен вообще.

всё начинается и заканчивается объявлением record'а прямо в коде программы - и вот этим библиотека просто замечательна
...
Рейтинг: 0 / 0
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Кто работал с Google Protocol Buffers ? Есть вопрос ! / 25 сообщений из 31, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]