我正在使用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;
}
我已经尝试将回调设置为extern“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];
}
答案 0 :(得分:4)
您可以使用.proto文件中的选项(nanopb).max_size = 123
为字符串字段指定最大大小,以避免回调。然后nanopb可以在结构中生成一个简单的char
数组(relevant part of documentation)。
关于为什么回调不起作用:只是猜测,但尝试也将extern "C"
添加到回调函数中。我假设你在那里使用C ++,所以也许在那个平台上,C和C ++调用约定不同,导致崩溃。
VxWorks串行控制台是否提供有关崩溃的更多信息?我不记得它是否适用于从LabView调用的函数,因此直接从VxWorks shell运行一些测试代码也值得一试。
答案 1 :(得分: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/