2015-07-10 3 views
0

Я использую Nanopb, чтобы попытаться отправить сообщения protobuf из VixWorks National Instruments Compact RIO (9025). Моя кросс-компиляция отлично работает, и я могу даже отправить полное сообщение с типами данных, которые не требуют дополнительной кодировки. То, что получает меня, - это обратные вызовы. Мой код перекрестно скомпилирован и вызывается из LabVIEW, и структура Nanopb на основе обратного вызова, похоже, прерывается (ошибка, авария, целевые перезагрузки и т. Д.) На целевой машине. Если я запускаю его без каких-либо обратных вызовов, он отлично работает.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 с максимальной длиной и либо не понял его правильно, либо он тоже не работал.

Если я удаляю строку из протокола proto и удаляю обратный вызов, он отлично работает. Похоже, что структура обратного вызова не будет работать в этой библиотечной среде 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]; 
} 

ответ

4

Вы можете избежать обратных вызовов, давая максимальный размер для поля строки с помощью опции (nanopb).max_size = 123 в файле .proto. Тогда nanopb может генерировать простой массив char в структуре (relevant part of documentation).

Относительно того, почему обратные вызовы не работают: просто предположите, но попробуйте добавить extern "C" также к функции обратного вызова. Я предполагаю, что вы используете C++ там, поэтому, возможно, на этой платформе соглашения о вызовах на C и C++ различаются и что приводит к сбою.

Имеется ли в последовательной консоли VxWorks больше информации о сбое? Я не помню, делает ли это это для функций, вызванных LabView, поэтому запуск тестового кода непосредственно из оболочки VxWorks может оказаться целесообразным.

+0

Я думал, что я попытался с помощью MAX_SIZE, но, возможно, не сделали это правильно и попробуйте еще раз , Я определенно попробовал добавить extern «C» к обратному вызову, и это не помогло. Я не дошел до вывода последовательной консоли, но попробую это сделать. Благодаря! –

+0

Итак, я попытался добавить параметр в поле в своем прото-файле, и генератор выплевывает: Опция «(nanopb)» неизвестна. Мысли? –

+0

@ChuckClaunch Вы должны добавить 'import 'nanopb.proto"; 'вверху: http://koti.kapsi.fi/jpa/nanopb/docs/reference.html#defining-the-options-in-the-op- proto-file – jpa

0

Возможно, первым препятствием является то, как код обрабатывает строки.

Собственное строковое представление LabVIEW не имеет нулевого конца, как C, но вы можете настроить LabVIEW на использование другого представления или обновить свой код для обработки собственного формата LabVIEW.

LabVIEW хранит строку в специальном формате, в котором первые четыре байта массива символов образуют 32-разрядное целое число со знаком, в котором хранится количество символов в строке. Таким образом, строка с n символами требует сохранения n + 4 байта в памяти.


LabVIEW Help: Использование массивов и строк в библиотеке Вызов функции узла
http://zone.ni.com/reference/en-XX/help/371361L-01/lvexcodeconcepts/array_and_string_options/

+0

Да! Определенно понимается в LabVIEW со строками. Я столкнулся с этим вопросом, исследуя это. Однако в моем конкретном случае LabVIEW никогда не касается строки (я передаю/удаляю массив uint8_t), поэтому я не думаю, что это моя проблема. Идея использования nanopb заключается в том, что он заботится обо всех кодировках, и все, с чем должен работать LabVIEW, - это исходный двоичный файл. –

Смежные вопросы