无法使用Google协议缓冲区从C#到C++再返回相同的double

本文关键字:返回 C++ double Google 协议 缓冲区 | 更新日期: 2023-09-27 18:22:14

我正在尝试在C#和C++之间进行通信,并取得了不同程度的成功。

我可以使用回复/请求在两者之间发送消息,但我收到的替身不正确。

为了调试和理解,我目前正在运行以下程序:

Clrzmq 3.0 rc1,Google ProtocolBuffer 2.5,Protobuf-csharp-port-2.4,ZeroMQ-3.2.3

.Proto

package InternalComm;
message Point 
{
    optional double x = 1;
    optional double y = 2;
    optional string label = 3;
}

server.cpp(相关部分)

while (true) {
    zmq::message_t request;
    // Wait for next request from client
    socket.recv (&request);
    zmq::message_t reply (request.size());
    memcpy ((void*)reply.data(), request.data(), request.size());
    socket.send(reply);
}

client.cs(相关部分)

public static Point ProtobufPoint(Point point)
    {
        Point rtn = new Point(0,0);
        using (var context = ZmqContext.Create())
        {
            using (ZmqSocket requester = context.CreateSocket(SocketType.REQ))
            {
                requester.Connect("tcp://localhost:5555");
                var p = InternalComm.Point.CreateBuilder().SetX(point.X).SetY(point.Y).Build().ToByteArray();
                requester.Send(p);
                string reply = requester.Receive(Encoding.ASCII);
                Console.WriteLine("Input: {0}", point);
                byte[] bytes = System.Text.Encoding.ASCII.GetBytes(reply);
                var message = InternalComm.Point.ParseFrom(bytes);
                rtn.X = message.X;
                rtn.Y = message.Y;
                Console.WriteLine("Output: {0}", rtn);
            }
        }
        return rtn;
    }

在C#方面,Point是一个非常简单的结构。只有x和y属性。

以下是运行上述代码后,我从单元测试中得到的结果。

输入(1.31616874365468、4.55516872325469)
输出(0.0004739179851157914.55516872323627)

输入(274.120398471829274.128936418736)
输出(274.077917334613、274.128936049925)

输入(150.123798461987,2.345E-12)
输出(145.976459594794,1.11014954927532E-13)

输入(150,0)
输出(145.96875,0)

我认为问题是我的protobuf代码不正确(怀疑这是Skeet方面的错误)。我还假设server.cpp对消息不做任何操作,但按原样返回。

想法?

无法使用Google协议缓冲区从C#到C++再返回相同的double

requestor.Receive(Encoding.ASCII)调用的目的是接收字符串,而不是字节块。您要求ZmqSocket实例将消息作为ASCII字符串返回,这极有可能导致对内容的修改。如果要发送字节数组,请接收字节数组。

试试这个:

int readSize;
byte[] reply = requester.Receive(null, out readSize);
var message = InternalComm.Point.ParseFrom(reply);

readSize变量将包含接收到的块中有效字节的实际数量,这可能与reply数组的大小不同,因此您可能需要对数组进行切片以使其符合ProtoBuf的要求。

为什么要执行ASCI-->字节-->解析步骤?如果您正在解析字节,则应该读取字节。如果您正在解析文本,您应该阅读它。

不必要的字符集转换看起来很可能是错误的。