17 Serialisation
R’s serialisation format converts an R object to a byte stream (and back) that can be written to a file, a connection, or a database. From C you can drive the same machinery serialize()/unserialize() use at the R level, either over a FILE * or over a custom byte source/sink you provide.
17.1 XDR encoding
XDR is the default binary serialisation format: big-endian and platform-independent, so streams are portable across architectures. These helpers encode and decode individual values when you implement a custom stream.
17.1.1 R_XDR_DOUBLE_SIZE(), R_XDR_INTEGER_SIZE()
Header: Rinternals.h
Specify the byte sizes of doubles and integers in XDR serialisation format.
#define R_XDR_DOUBLE_SIZE 8
#define R_XDR_INTEGER_SIZE 417.1.2 R_XDREncodeDouble(), R_XDRDecodeDouble(), R_XDREncodeInteger(), R_XDRDecodeInteger()
Header: Rinternals.h
Encode and decode doubles and integers in XDR format.
void R_XDREncodeDouble(double d, void *buf);
double R_XDRDecodeDouble(void *buf);
void R_XDREncodeInteger(int i, void *buf);
int R_XDRDecodeInteger(void *buf);Returns: R_XDRDecodeDouble() and R_XDRDecodeInteger() return the value decoded from buf.
17.2 Persistence streams
A persistence stream pairs a byte source/sink with optional persistence hooks. The hook function (phook, with its data pdata) is called for objects that can’t be serialised by value — external pointers and weak references — letting you substitute a placeholder on output and reconstruct the object on input; pass NULL to refuse such objects with an error. The version argument selects the serialisation format version (2, or 3 which supports ALTREP; version 3 output requires R >= 3.6.0 to read).
Note that WRE describes this framework as highly experimental for package use: it may change or be dropped in a future R release. Don’t depend on the fields of the stream structs directly — initialise them with the functions below.
typedef void *R_pstream_data_t;
typedef enum {
R_pstream_any_format,
R_pstream_ascii_format,
R_pstream_binary_format,
R_pstream_xdr_format,
R_pstream_asciihex_format
} R_pstream_format_t;
typedef struct R_outpstream_st *R_outpstream_t;
struct R_outpstream_st {
R_pstream_data_t data;
R_pstream_format_t type;
int version;
void (*OutChar)(R_outpstream_t, int);
void (*OutBytes)(R_outpstream_t, void *, int);
SEXP (*OutPersistHookFunc)(SEXP, SEXP);
SEXP OutPersistHookData;
};
typedef struct R_inpstream_st *R_inpstream_t;
struct R_inpstream_st {
R_pstream_data_t data;
R_pstream_format_t type;
int (*InChar)(R_inpstream_t);
void (*InBytes)(R_inpstream_t, void *, int);
SEXP (*InPersistHookFunc)(SEXP, SEXP);
SEXP InPersistHookData;
};The connection interface is not available to packages. To allow limited use of connection pointers, defining NEED_CONNECTION_PSTREAMS before including Rinternals.h defines the opaque pointer type:
#ifdef NEED_CONNECTION_PSTREAMS
#ifndef HAVE_RCONNECTION_TYPEDEF
typedef struct Rconn *Rconnection;
#define HAVE_RCONNECTION_TYPEDEF
#endif
#endif17.2.1 R_InitInPStream(), R_InitOutPStream()
experimental
Header: Rinternals.h
Initialise a custom input or output persistence stream.
void R_InitInPStream(R_inpstream_t stream, R_pstream_data_t data,
R_pstream_format_t type,
int (*inchar)(R_inpstream_t),
void (*inbytes)(R_inpstream_t, void *, int),
SEXP (*phook)(SEXP, SEXP), SEXP pdata);
void R_InitOutPStream(R_outpstream_t stream, R_pstream_data_t data,
R_pstream_format_t type, int version,
void (*outchar)(R_outpstream_t, int),
void (*outbytes)(R_outpstream_t, void *, int),
SEXP (*phook)(SEXP, SEXP), SEXP pdata);17.2.2 R_InitFileInPStream(), R_InitFileOutPStream()
experimental
Header: Rinternals.h
Initialise a persistence stream that reads from or writes to a file.
void R_InitFileInPStream(R_inpstream_t stream, FILE *fp,
R_pstream_format_t type,
SEXP (*phook)(SEXP, SEXP), SEXP pdata);
void R_InitFileOutPStream(R_outpstream_t stream, FILE *fp,
R_pstream_format_t type, int version,
SEXP (*phook)(SEXP, SEXP), SEXP pdata);17.3 Serialising objects
With a stream initialised, these two functions do the actual work:
17.3.1 R_Serialize(), R_Unserialize()
experimental needs protect throws
Header: Rinternals.h
R equivalent: serialize()
Serialise an R object to an output stream, or unserialise it from an input stream.
void R_Serialize(SEXP s, R_outpstream_t ops);
SEXP R_Unserialize(R_inpstream_t ips);Returns: R_Unserialize() returns the unserialised object; freshly allocated and unprotected.
The SEXP returned by R_Unserialize() is freshly allocated and must be protected from garbage collection.