序列化——它是什么,为什么我们需要它?

113

什么是序列化,为什么我们需要它?

我很难相信从C#发送一个int到C代码时不能直接通过简单的起始和终止信号来传输32位数据,而需要进行序列化。为什么C#不能只将这32位数据发送给C代码并告诉它这是一个int呢?

如果有任何关于为什么我们需要序列化以及如何使用它的好教程或网站,请分享一下。


3
实际上,你只需要发送带有起始和终止信号的32位数据。这相当于为 int 编写自己的编组代码。但是,如果要将 Dictionary<CustomClassA,List<CustomClassB>> 传递给 C 代码,该怎么办呢? - Vinko Vrsalovic
4
当你说 "over the wire" 时,字节序(Endianness)会浮现在脑海中。 - user7116
true表示忽略大小端或任何其他变体。 - george9170
62
这是一个有点奇怪的问题。这有点像问“为什么我们需要邮政系统,而不是让信使收集信件,将其带到中央地点进行分类,然后交付给收件人?”但...那就是邮政系统。你问为什么我们需要编组系统,当我们可以有...编组系统。我觉得我没有理解你的问题重点。你能澄清一下吗? - Eric Lippert
1
我认为理解这个问题的最佳方法是了解汇编语言中“方法”的工作原理——如何将最后一条指令地址保存在堆栈上,通过堆栈传递参数,方法修改堆栈指针寄存器,使用指令指针寄存器,以及特别是不同实现方法可能存在的细微差异。实际上,理解“电路”应该能够阐明你的问题。 - ylax
6个回答

88

由于不同的语言和环境具有不同的调用约定、布局约定、基元大小(例如 C# 中的 char 和 C 中的 char)、不同的对象创建/销毁约定和不同的设计准则。你需要一种方法将托管代码的数据传输到非托管代码中并反之亦然,以便它们能够看到和理解彼此。这就是所谓的“marshalling”。


36

.NET代码(C#,VB)之所以称为“托管代码”,是因为它受到CLR (通用语言运行时)的“管理”。

如果您使用C或C ++或汇编语言编写代码,则称其为“非托管代码”,因为没有涉及CLR。您需要负责所有内存分配/释放。

驱动是连接托管代码和非托管代码的过程之一; 这是CLR提供的最重要服务之一。


13

将一个 int 进行序列化最理想的情况就是如你所说:将其从CLR的托管堆栈中复制到C代码可以访问的某个地方。而序列化字符串、对象、数组和其他类型则是比较困难的事情。

但是P/Invoke互操作层几乎为你处理了所有这些事情。


4
马歇尔操作实际上是在执行复制操作吗?我正在进行实时图像处理操作,希望不需要对内存中的所有内容进行复制。 - ias

11

正如Vinko在评论中所说,您可以传递原始类型而不需要任何特殊的编组。这些称为“可平坦化”类型,包括byte、short、int、long等类型及其无符号对应类型。

此页面包含可平坦化和不可平坦化类型列表


9

Marshalling(编组)是一种“媒介”,或者说是一种通往非托管世界数据类型的网关,反之亦然。通过使用PInvoke(平台调用),它可以确保以安全的方式返回数据。


4

Marshalling(编组)是将函数签名传递给位于不同机器上的另一个进程,通常通过将结构化数据转换为专用格式来实现,该格式可以传输到其他处理器系统(序列化/反序列化)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接