【发布时间】:2021-12-19 10:58:05
【问题描述】:
我正在尝试从 C# 中的 byte[] 反序列化我的 protobuf 数据。数据来自命名管道上的另一个 C++ 程序。我在两端打印字节(或无符号字符)数组,数组的字节和长度完全相同。尽管我在尝试反序列化数据时遇到了无效标记(零)错误。相关的代码部分是:
从 C++ 发送数据:
bool writeOutputMessage(HANDLE hPipe, const CubesExample::OutputMessage& outputMessage)
{
int messageBytes = outputMessage.ByteSizeLong();
char buffer[messageBytes + 4];
outputMessage.SerializeToArray(&buffer + 4, messageBytes);
memcpy(buffer, &messageBytes, 4);
messageBytes += 4;
DWORD bytesWritten = 0;
std::cout << std::string("Writing ") + std::to_string(messageBytes) + " bytes" << std::endl;
std::cout << "Sending bytes";
for(char c : buffer) std::cout << " " << +static_cast<unsigned char>(c);
std::cout << std::endl;
BOOL fSuccess = WriteFile(
hPipe, // handle to pipe
buffer, // buffer to write from
messageBytes, // number of bytes to write
&bytesWritten, // number of bytes written
NULL); // not overlapped I/O
if (!fSuccess || bytesWritten != messageBytes)
{
std::cout << "InstanceThread WriteFile failed, GLE=" << GetLastError() << std::endl;
return false;
}
return true;
}
在 C# 中接收数据:
public byte[] readOutputMessage()
{
int readBytes = 0;
byte[] messageSizeBuf = new byte[4];
readBytes = fromagent_pipe.Read(messageSizeBuf, 0, 4);
if(readBytes != 4)
{
Debug.Log("Failed to read message size!");
return null;
}
int messageSize = BitConverter.ToInt32(messageSizeBuf, 0);
Debug.Log("Attempting to read message of size: " + messageSize);
byte[] buffer = new byte[messageSize];
readBytes = 0;
readBytes = fromagent_pipe.Read(buffer, 0, messageSize);
if(readBytes != messageSize)
{
Debug.Log("Read " + readBytes + " bytes but expected " + messageSize);
return null;
}
return buffer;
}
在 C# 中解析字节:
byte[] buffer = inputTask.Result;
string bytes = "";
foreach(byte b in buffer) bytes += " " + (uint)b;
Debug.Log("Got bytes: " + bytes + " Length: " + buffer.Length);
if(buffer != null)
{
OutputMessage outputMessage = OutputMessage.Parser.ParseFrom(buffer);
inputMotion = new UnityEngine.Vector2(outputMessage.MovementDirection.XPos, outputMessage.MovementDirection.YPos);
}
另外,这里是 C++ 进程的输出:
Writing 11 bytes
Sending bytes 7 0 0 0 227 0 0 0 72 57 201
以及来自 C# 进程的输出:
Attempting to read message of size: 7
Got bytes: 227 0 0 0 72 57 201 Length: 7
写入过程写入 4 个字节,指示消息的大小,然后是消息字节。在这种情况下,消息大小为 7,因此写入过程总共写入了 11 个字节。
如您所见,字节完全相同,但对OutputMessage.Parser.ParseFrom(buffer) 的调用仍然失败,标签无效(零)。
我错过了什么?
感谢任何提前阅读的人。
编辑: 发送的消息正在创建如下:
CubesExample::OutputMessage outputMessage;
CubesExample::Vector2* moveDir = outputMessage.mutable_movementdirection();
moveDir->set_xpos(1.0f);
moveDir->set_ypos(0.0f);
【问题讨论】:
-
您发送的数据全是零,看起来有点滑稽。您的消息中包含哪些数据类型?当我尝试使用在线 protobuf 反序列化器反序列化数据时,我什么也得不到。这可能是由于数据无效。
-
OutputMessage 有一个 Vector2 消息,里面有 2 个浮点数。这就是我创建消息的方式: CubesExample::OutputMessage outputMessage; CubesExample::Vector2* moveDir = outputMessage.mutable_movementdirection(); moveDir->set_xpos(1.0f); moveDir->set_ypos(0.0f);
-
浮点数是 4 个字节长,每个字段需要一个至少一个字节的标签。所以看起来你缺少三个字节。
-
outputMessage.ByteSizeLong() 不断返回 7。你知道为什么吗?
-
我将浮点数从 1.0f、0.0f 更改为 1.0f、2.0f,消息大小增加到 12 个字节。当浮点值为 0.0f 时似乎有一个优化
标签: c# c++ protocol-buffers