Nanopb без обратных вызовов
Я использую Nanopb, чтобы попытаться отправить протобуф-сообщения от National Instruments Compact RIO на базе VxWorks (9025). Моя кросс-компиляция работает отлично, и я даже могу отправить полное сообщение с типами данных, которые не требуют дополнительного кодирования. Что меня заводит, так это обратные вызовы. Мой код кросс-компилируется и вызывается из LabVIEW, и структура Nanopb, основанная на обратном вызове, кажется, ломается (ошибка, сбой, перезагрузка цели, что угодно) на целевой машине. Если я запускаю его без каких-либо обратных вызовов, он прекрасно работает.
Вот код, о котором идет речь:
bool encode_string(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
{
char *str = "Woo hoo!";
if (!pb_encode_tag_for_field(stream, field))
return false;
return pb_encode_string(stream, (uint8_t*)str, strlen(str));
}
extern "C" uint16_t getPacket(uint8_t* packet)
{
uint8_t buffer[256];
uint16_t packetSize;
ExampleMsg msg = {};
pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
msg.name.funcs.encode = &encode_string;
msg.value = 17;
msg.number = 18;
pb_encode(&stream, ExampleMsg_fields, &msg);
packetSize = stream.bytes_written;
memcpy(packet, buffer, 256);
return packetSize;
}
И вот файл прото:
syntax = "proto2"
message ExampleMsg {
required int32 value = 1;
required int32 number = 2;
required string name = 3;
}
Я также пытался сделать обратный вызов внешним C, и это ничего не изменило. Я также попытался добавить файл опций nanopb с максимальной длиной и либо неправильно его понял, либо он тоже не работал.
Если я удаляю строку из прототипа сообщения и удаляю обратный вызов, он прекрасно работает. Кажется, что структура обратного вызова не будет работать в этой среде библиотеки LabVIEW -> C. Есть ли другой способ, которым я могу кодировать сообщение без структуры обратного вызова? Или как-то встроить обратный вызов в функцию getPacket()?
Обновленный код:
extern "C" uint16_t getPacket(uint8_t* packet)
{
uint8_t buffer[256];
for (unsigned int i = 0; i < 256; ++i)
buffer[i] = 0;
uint16_t packetSize;
ExampleMsg msg = {};
pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
msg.name.funcs.encode = &encode_string;
msg.value = 17;
msg.number = 18;
char name[] = "Woo hoo!";
strncpy(msg.name, name, strlen(name));
pb_encode(&stream, ExampleMsg_fields, &msg);
packetSize = stream.bytes_written;
memcpy(packet, buffer, sizeof(buffer));
return packetSize;
}
Обновленный файл прото:
syntax = "proto2"
import "nanopb.proto";
message ExampleMsg {
required int32 value = 1;
required int32 number = 2;
required string name = 3 [(nanopb).max_size = 40];
}
2 ответа
Вы можете избежать обратных вызовов, задав максимальный размер для строкового поля, используя опцию (nanopb).max_size = 123
в.proto файле. Тогда Nanopb может генерировать простой char
массив в структуре ( соответствующая часть документации).
Относительно того, почему обратные вызовы не работают: просто предположение, но попробуйте добавить extern "C"
также к функции обратного вызова. Я предполагаю, что вы используете C++ там, поэтому, возможно, на этой платформе соглашения о вызовах C и C++ различаются, и это вызывает сбой.
Предоставляет ли последовательная консоль VxWorks дополнительную информацию о сбое? Я не помню, так ли это для функций, вызываемых из LabView, поэтому стоит попробовать запустить тестовый код непосредственно из оболочки VxWorks.
Возможно, первое препятствие заключается в том, как код обрабатывает строки.
Собственное строковое представление LabVIEW не заканчивается нулем, как C, но вы можете настроить LabVIEW на использование другого представления или обновить код для обработки нативного формата LabVIEW.
LabVIEW хранит строку в специальном формате, в котором первые четыре байта массива символов образуют 32-разрядное целое число со знаком, в котором хранится количество символов в строке. Таким образом, строка с n символами требует n + 4 байта для хранения в памяти.
Справка LabVIEW: использование массивов и строк в узле функции библиотеки вызовов
http://zone.ni.com/reference/en-XX/help/371361L-01/lvexcodeconcepts/array_and_string_options/