1

我正在使用以下设计在 2 个应用程序之间发送消息。

class InternalMessage
{
public:


InternalMessage(unsigned int messageId, unsigned int messageSize, INTERNAL_MESSAGE_TYPE messageType)
               : messageId_(messageId), messageSize_(messageSize), messageType_(messageType) {}
virtual ~InternalMessage() {}


protected:
unsigned int messageId_;
unsigned int messageSize_;
INTERNAL_MESSAGE_TYPE messageType_;
};

然后还有其他几个使用继承的消息:

class KeyPressMessage : public InternalMessage
{
public:
KeyPressMessage () : InternalMessage(RADIO_KEY_PRESS_MESSAGE_ID, sizeof(KeyPressMessage ), EVENT_MESSAGE_TYPE),
                         key_(INVALID_KEY) {}

virtual ~KeyPressMessage () {}


}


private:
KEY key_;
};

在接收消息时,我们使用基类指针:

MsgHandler(InternalMessage* )

在发送消息时,我们使用派生类 sizeof 来计算要发送的字节数:

sizeof(KeyPressMessage )

使用这种设计似乎很糟糕,因为 sizeof 派生类包含虚拟表(可以在 32 位和 64 位操作系统之间更改)。我想问一下是否有更好的 ICD 实现消息处理程序和发送方/接收方的方法?我需要一些序列化/反序列化吗?

4

2 回答 2

2

sizeof()使用不同的编译器/构建选项时,即使在相同的操作系统上也可能会给您不同的结果。在编写通过网络或外部进程运行的代码时,您确实需要编写序列化/反序列化代码。

在您的示例中,情况更糟:您正在编写指针(VTBL),这对另一个进程没有意义 - 它可能具有不同的内存布局并且函数将位于不同的地址。

有两种处理序列化的方法:

  • 一个一个地写入和读取字段。

    非常简单且非常便携。虽然代码量比其他选项要大一些,但它为控制类型长度和字节序提供了好处。

  • 使用打包的 POD 数据结构。

    好吧,只有原始类型,编译器被强制不对齐它们,所以它们总是采用相同的大小(假设数据类型是固定的)。

为确保一切正常,您必须:

  • 仅使用固定长度的数据类型。没有int。从 C99使用int32_t和类似。
  • 确保数据封送始终使用相同的字节序。
于 2015-02-15T09:16:12.867 回答
1

此外,虚拟指针不会在新进程中指向正确的地址,所以整个事情都会失败。这是 UB,通常是一个糟糕的主意。您需要将其正确序列化为某种格式,而不仅仅是memcpy周围。

于 2015-02-15T09:12:40.320 回答