问题描述
我正在使用 Nanopb 尝试从基于VxWorks的National Instruments发送protobuf消息紧凑型RIO(9025).我的交叉编译效果很好,甚至可以发送不需要额外编码的数据类型的完整消息.让我着迷的是回调.我的代码是通过LabVIEW交叉编译和调用的,基于Nanopb的基于回调的结构似乎在目标计算机上中断(错误,崩溃,目标重新启动等).如果我在没有任何回调的情况下运行它,则效果很好.
I'm using Nanopb to try and send protobuf messages from a VxWorks based National Instruments Compact RIO (9025). My cross compilation works great, and I can even send a complete message with data types that don't require extra encoding. What's getting me is the callbacks. My code is cross compiled and called from LabVIEW and the callback based structure of Nanopb seems to break (error out, crash, target reboots, whatever) on the target machine. If I run it without any callbacks it works great.
这是有问题的代码:
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选项文件,或者它不能正确理解它,或者它也不起作用.
I have tried making the callback an extern "C" as well and it didn't change anything. I've also tried adding a nanopb options file with a max length and either didn't understand it correctly or it didn't work either.
如果我从原始消息中删除字符串并删除回调,则效果很好.在该LabVIEW-> C库环境中,回调结构似乎无法正常工作.没有回调结构,还有其他方法可以编码消息吗?还是以某种方式将回调嵌入到getPacket()函数中?
If I remove the string from the proto message and remove the callback, it works great. It seems like the callback structure is not going to work in this LabVIEW -> C library environment. Is there another way I can encode the message without the callback structure? Or somehow embed the callback into the getPacket() function?
更新的代码:
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];
}
推荐答案
通过使用.proto文件中的选项(nanopb).max_size = 123
为字符串字段提供最大大小,可以避免回调.然后,nanopb可以在结构中生成一个简单的char
数组(相关文档的一部分).
You can avoid callbacks by giving a maximum size for the string field using the option (nanopb).max_size = 123
in the .proto file. Then nanopb can generate a simple char
array in the structure (relevant part of documentation).
关于为什么回调不起作用:只是一个猜测,但是请尝试将extern "C"
也添加到回调函数中.我假设您在那里使用C ++,所以也许在该平台上C和C ++的调用约定不同,这会导致崩溃.
Regarding why callbacks don't work: just a guess, but try adding extern "C"
also to the callback function. I assume you are using C++ there, so perhaps on that platform the C and C++ calling conventions differ and that causes the crash.
VxWorks串行控制台是否提供有关崩溃的更多信息?我不记得是否对从LabView调用的函数执行此操作,因此直接从VxWorks shell运行一些测试代码也值得一试.
Does the VxWorks serial console give any more information about the crash? I don't remember if it does that for functions called from LabView, so running some test code directly from the VxWorks shell may be worth a try also.
这篇关于无回调的Nanopb的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!