This package provides R with access to cereal header files. cereal is a header-only C++11 serialization library. cereal takes arbitrary data types and reversibly turns them into different representations, such as compact binary encodings, XML, or JSON.
For more information, please visit the official website of the cereal project: https://uscilab.github.io/cereal/.
The headers in this package can be used via:
LinkingTo:
field in the DESCRIPTION of an R
package;[[cpp11::linking_to("Rcereal")]]
attribute and
cpp11::source
from the cpp11 package, or;[[Rcpp::depends(Rcereal)]]
Rcpp
attribute.The latest release can be installed from CRAN via:
install.packages('Rcereal')
Use remotes::install_github
to install the latest
version of Rcereal. Optionally: use
Rcereal::update_version
to over-write the header files in
the R library with a version from https://github.com/USCiLab/cereal.
::install_github("wush978/Rcereal")
remotes::update_version() # optional Rcereal
See the official cereal Quick Start guide for further details about using cereal in C++11.
The following example shows how to use Rcereal
alongside cpp11 to serialize and
deserialize a user-defined struct
using raw vectors:
// path/to/example.cpp
#include <sstream>
#include <cpp11/raws.hpp>
#include <cereal/archives/binary.hpp>
struct MyClass
{
int x, y, z;
// This method lets cereal know which data members to serialize
template<class Archive>
void serialize(Archive & archive)
{
( x, y, z ); // serialize things by passing them to the archive
archive}
};
[[cpp11::linking_to("Rcereal")]]
[[cpp11::register]]
::raws serialize_myclass(int x = 1, int y = 2, int z = 3) {
cpp11{ x, y, z };
MyClass my_instance std::stringstream ss;
{
::BinaryOutputArchive oarchive(ss); // Create an output archive
cereal(my_instance);
oarchive}
.seekg(0, ss.end);
ss::writable::raws result(ss.tellg());
cpp11.seekg(0, ss.beg);
ssstd::copy(std::istreambuf_iterator<char>{ss},
std::istreambuf_iterator<char>(),
.begin());
resultreturn result;
}
[[cpp11::register]]
void deserialize_myclass(cpp11::raws src) {
std::stringstream ss;
std::copy(src.cbegin(), src.cend(), std::ostream_iterator<char>(ss));
;
MyClass my_instance{
::BinaryInputArchive iarchive(ss); // Read from input archive
cereal(my_instance);
iarchive}
("%i,%i,%i\n", my_instance.x, my_instance.y, my_instance.z);
Rprintf}
Then, provided C++11 is enabled by default (see this tidyverse post 03/2023), in R:
::cpp_source(file='path/to/example.cpp')
cpp11<- serialize_myclass(1, 2, 4)
raw_vector deserialize_myclass(raw_vector)
The following example shows how to use Rcereal
alongside Rcpp to
serialize and deserialize a user-defined struct
using raw
vectors:
// path/to/example.cpp
//[[Rcpp::depends(Rcereal)]]
#include <sstream>
#include <cereal/archives/binary.hpp>
#include <Rcpp.h>
using namespace Rcpp;
struct MyClass
{
/* same as cpp11 example above */
};
//[[Rcpp::export]]
::RawVector serialize_myclass(int x = 1, int y = 2, int z = 3) {
Rcpp{ x, y, z };
MyClass my_instance std::stringstream ss;
{
::BinaryOutputArchive oarchive(ss); // Create an output archive
cereal(my_instance);
oarchive}
.seekg(0, ss.end);
ss::RawVector result(ss.tellg());
Rcpp.seekg(0, ss.beg);
ss.read(reinterpret_cast<char*>(&result[0]), result.size());
ssreturn result;
}
//[[Rcpp::export]]
void deserialize_myclass(Rcpp::RawVector src) {
std::stringstream ss;
.write(reinterpret_cast<char*>(&src[0]), src.size());
ss.seekg(0, ss.beg);
ss;
MyClass my_instance{
::BinaryInputArchive iarchive(ss);
cereal(my_instance);
iarchive}
::Rcout << my_instance.x << "," << my_instance.y << "," <<
Rcpp.z << std::endl;
my_instance}
Then in R, provided C++ is enabled by default:
::sourceCpp("path/to/example.cpp")
Rcpp<- serialize_myclass(1, 2, 4)
raw_vector deserialize_myclass(raw_vector)
C++11 may not be enabled by default for some compilers, if not;
ensure that PKG_CXXFLAGS
contains -std=c++11
,
e.g. if you use pkgbuild::compile_dll()
to build a package
(similarly for devtools::build
):
::with_makevars(c("PKG_CXXFLAGS"="std=c++11"),
withr::compile_dll(),
pkgbuildassignment="+=")
If the compiler reports missing header files, try
Rcereal::update_version()
to update the content of
cereal from GitHub. Check that a directory named
cereal
is in the folder
system.file("include", package = "Rcereal")
.