FlatBuffers:C++ 编码与 C# 编码,C# 解码端到端示例

FlatBuffers: Encoding in C++ versus C#, decoding in C# end-to-end example

想象一个模式:

namespace MyEvents;  

table EventAddress  
{  
  id:uint;  
  timestamp:ulong;  
  adress:string;  
}  

table EventSignalStrength  
{  
  id:uint;  
  timestamp:ulong; 
  strength:float;   
}  

table EventStatus  
{  
  status:string;  
}  

union Events {EventAddress, EventSignalStrength, EventStatus}  

table EventHolder  
{  
  theEvent:Events;  
}  

root_type EventHolder;  

对于状态消息 "EXIT",在 C++ 中,我编码并通过网络发送,如下所示:

std::string message("EXIT");  
flatbuffers::FlatBufferBuilder builder;  
auto messageString= builder.CreateString(message);  // Message to send.  
auto statusEvent= MyEvents::CreateEventStatus(builder, messageString);  
auto eventHolder= MyEvents::CreateEventHolder(builder, MyEvents::Events_EventStatus, statusEvent.Union());  
builder.Finish(eventHolder);  

// Code to decode to check my work omitted, but the data decode properly in my real-world application.  

ret= sendto(m_udpSocket, reinterpret_cast<const char*>(builder.GetBufferPointer()), static_cast<int>(builder.GetSize()), 0, reinterpret_cast<SOCKADDR *>(&m_destination), sizeof(m_destination));  

对于相同的消息,"EXIT",我在 C# 中编码并通过网络发送,如:

string message= "EXIT";  
FlatBufferBuilder builder = new FlatBufferBuilder(1);  
StringOffset messageOffset = builder.CreateString(message);  
EventStatus.StartEventStatus(builder);  
EventStatus.AddStatus(builder, messageOffset);  
Offset<EventStatus> eventStatusOffset = EventStatus.EndEventStatus(builder);  

EventHolder.StartEventHolder(builder);  
EventHolder.AddTheEventType(builder, Events.EventStatus);  
EventHolder.AddTheEvent(builder, eventStatusOffset.Value);  
Offset<EventHolder> eventHolderOffset = EventHolder.EndEventHolder(builder);  

EventHolder.FinishEventHolderBuffer(builder, eventHolderOffset);  

// Test the encoding by decoding:  
EventHolder flatBuffer = EventHolder.GetRootAsEventHolder(builder.DataBuffer);  
Events flatBufferType = flatBuffer.TheEventType;  // Type looks good.  
EventStatus decodedEvent= new EventStatus();  
flatBuffer.GetDataObject<EventStatus>(decodedEvent);  // decodedEvent.Status looks good.  

// This code seems to send the correct data:  
Byte[] sendSized = builder.SizedByteArray();  
udpClient.Send(sendSized, sendSized.Length);  

// This code does not seem to send the correct data:  
//ByteBuffer sendByteBuffer = builder.DataBuffer;  
//udpClient.Send(sendByteBuffer.Data, sendByteBuffer.Data.Length);  

在我用 C# 编写的客户端应用程序中,我解码为:

Byte[] receiveBytes = udpClient.Receive(ref m_remoteEndpoint);  
ByteBuffer flatBufferBytes= new ByteBuffer(receiveBytes);  
EventHolder flatBuffer = EventHolder.GetRootAsEventHolder(flatBufferBytes);  
Events flatBufferType= flatBuffer.DataObjectType;  
EventAddress eventAddress = null;  
EventSignalStrength eventSignalStrength = null;  
EventStatus eventStatus = null;  
switch (flatBufferType)  
{  
  case Events.EventAddress:  
  {  
    eventAddress = new EventAddress();  
    flatBuffer.GetDataObject<EventAddress>(eventAddress);  
    ProcessEventAddress(eventAddress);  
    break;  
  }  

  case Events.EventSignalStrength:  
  {  
    eventSignalStrength = new EventSignalStrength();  
    flatBuffer.GetDataObject<EventSignalStrength>(eventSignalStrength);  
    ProcessEventSignalStrength(eventSignalStrength);  
    break;  
  }  

  case Events.EventStatus:  
  {  
    eventStatus= new EventStatus();  
    flatBuffer.GetDataObject<EventStatus>(eventStatus);  
    Console.WriteLine("\nStatus Message: {0}", eventStatus.status);  
    break;  
  }  
}  

最初,来自 C# 发件人的消息没有正确解码 - 现在可以了。我对发件人进行了更改,所以可能没有重建。

感谢任何意见。

ByteBuffer 包含缓冲区,但不一定位于偏移量 0,所以是的,将其转换为字节数组(或从其起始偏移量发送字节缓冲区内容)是唯一正确的发送方式。

不同语言的编码可能不同,因为实现可能以不同的顺序序列化事物。这里C++实现决定把联合类型字段写在偏移量之前,刚好对齐效率不高,所以大了一点。 C# 做相反的事情。