0

我正在使用Nanopb尝试从基于 VxWorks 的 National Instruments Compact RIO (9025) 发送 protobuf 消息。我的交叉编译效果很好,我什至可以发送包含不需要额外编码的数据类型的完整消息。让我感动的是回调。我的代码是从 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];
}
4

2 回答 2

5

(nanopb).max_size = 123您可以通过使用.proto 文件中的选项为字符串字段指定最大大小来避免回调。然后 nanopb 可以char在结构中生成一个简单的数组(文档的相关部分)。

关于为什么回调不起作用:只是一个猜测,但尝试extern "C"也添加到回调函数中。我假设您在那里使用 C++,所以在那个平台上,C 和 C++ 调用约定可能不同,这会导致崩溃。

VxWorks 串行控制台是否提供有关崩溃的更多信息?我不记得它是否对从 LabView 调用的函数执行此操作,因此直接从 VxWorks shell 运行一些测试代码可能也值得一试。

于 2015-07-10T16:19:37.337 回答
0

也许第一个障碍是代码如何处理字符串。

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/

于 2015-07-10T16:20:58.127 回答