module Marshal: Marshal
type
extern_flags =
| |
No_sharing |
(* | 不保留共享 | *) |
| |
闭包 |
(* | 发送函数闭包 | *) |
| |
Compat_32 |
(* | 确保 32 位兼容性 | *) |
下面 Marshal.to_*
函数的标志。
val to_channel : out_channel -> 'a -> extern_flags list -> unit
Marshal.to_channel chan v flags
将 v
的表示形式写入通道 chan
。 flags
参数是一个可能为空的标志列表,用于控制关于共享、函数值以及 32 位和 64 位平台之间兼容性的编组行为。
如果 flags
不包含 Marshal.No_sharing
,则会检测值 v
内部的循环和共享,并在生成的字节序列中保留这些信息。特别是,这保证了编组始终会终止。连续调用 Marshal.to_channel
编组的值之间的共享既不会被检测到,也不会被保留。如果 flags
包含 Marshal.No_sharing
,则会忽略共享。如果 v
不包含共享的子结构,这将导致更快的编组,但如果 v
实际上包含共享,或者甚至包含循环,则可能会导致编组速度变慢和字节表示形式更大,甚至导致不终止。
如果 flags
不包含 Marshal.Closures
,则在遇到 v
内部的函数值时,编组将失败:只有“纯”数据结构(不包含函数或对象)才能安全地在不同程序之间传输。如果 flags
包含 Marshal.Closures
,则函数值将被编组为程序代码中的位置以及对应于闭包中捕获的自由变量的值。在这种情况下,编组的输出只能在运行完全相同程序且编译代码完全相同的进程中读取。(这在解编组时使用代码位置一起传输的代码的 MD5 摘要进行检查。)
闭包中捕获哪些自由变量的精确定义未指定,并且在字节码和原生代码之间可能有所不同(并根据优化标志)。特别是,访问全局引用的函数值可能包含也可能不包含其闭包中的引用。如果包含,则解编组相应的闭包将创建一个新的引用,该引用与全局引用不同。
如果 flags
包含 Marshal.Compat_32
,则在遇到超出 32 位平台上可表示的整数范围 -2
30
, 2
30
-1
的整数值时,编组将失败。这确保了在 64 位平台上生成的数据可以安全地在 32 位平台上读回。如果 flags
不包含 Marshal.Compat_32
,则会编组超出范围 -2
30
, 2
30
-1
的整数值,并且可以在 64 位平台上读回,但在 32 位平台上读回时会在解编组时导致错误。 Mashal.Compat_32
标志仅在 64 位平台上执行编组时才重要;如果在 32 位平台上执行编组,则它没有任何作用。
Failure
,如果 chan
不是以二进制模式打开。val to_bytes : 'a -> extern_flags list -> bytes
Marshal.to_bytes v flags
返回一个包含 v
表示形式的字节序列。 flags
参数与 Marshal.to_channel
的含义相同。
val to_string : 'a -> extern_flags list -> string
与 to_bytes
相同,但返回结果为字符串而不是字节序列。
val to_buffer : bytes -> int -> int -> 'a -> extern_flags list -> int
Marshal.to_buffer buff ofs len v flags
编组值 v
,将其字节表示形式存储在序列 buff
中,从索引 ofs
开始,最多写入 len
个字节。它返回实际写入序列的字节数。如果 v
的字节表示形式不适合 len
个字符,则会引发 Failure
异常。
val from_channel : in_channel -> 'a
Marshal.from_channel chan
从通道 chan
读取结构化值的字节表示形式(由其中一个 Marshal.to_*
函数生成),并重建并返回相应的值。
End_of_file
,如果 chan
已经到达文件末尾。Failure
,如果在解编组本身过程中到达文件末尾,或者 chan
不是以二进制模式打开。val from_bytes : bytes -> int -> 'a
Marshal.from_bytes buff ofs
解编组结构化值,类似于 Marshal.from_channel
,除了字节表示形式不是从通道读取的,而是从字节序列 buff
中读取的,从位置 ofs
开始。字节序列不会被修改。
val from_string : string -> int -> 'a
与 from_bytes
相同,但接受字符串作为参数而不是字节序列。
val header_size : int
表示编组值的字节由一个固定大小的头部和一个可变大小的数据部分组成,其大小可以从头部确定。 Marshal.header_size
是头部的字节大小。 Marshal.data_size
buff ofs
是数据部分的字节大小,假设有效的头部存储在从位置 ofs
开始的 buff
中。最后, Marshal.total_size
buff ofs
是编组值的总字节大小。如果 buff
, ofs
不包含有效的头部,则 Marshal.data_size
和 Marshal.total_size
都将引发 Failure
。
要将编组值的字节表示形式读入字节序列,程序需要首先将 Marshal.header_size
个字节读入序列,然后使用 Marshal.data_size
确定表示形式其余部分的长度,确保序列足够大以容纳剩余数据,然后读取它,最后调用 Marshal.from_bytes
来解编组该值。
val data_size : bytes -> int -> int
val total_size : bytes -> int -> int
在编组可能被不同域修改的可变值时必须小心。修改正在编组的值(即转换为字节序列)是一个编程错误,并且由于撕裂,可能会导致意外的值(在解编组时),因为编组涉及逐字节复制。