A blob is a Binary Large Object, an undigested bunch of stuff.
The S statistical computing language (and R is a dialect of S) is call by value. Every time an object passes through a function call a copy is made. For large objects this may result in severe memory usage problems. Whether this is a defect in the S language or not is a matter of opinion. Call by value is fundamental to the S style. It cannot be changed.
However, it can be worked around, and Luke Tierney put hooks in
R to so work around. An R object of class "externalptr"
is a pointer to a blob. R itself has no idea what to do with it,
but it is an R object like any other. It can be copied (meaning the pointer
is copied but not the data it points to), passed to functions, or put into
a list. You can do anything with it you can do to any R object
except (in R) access the data it points to.
The blob must be created by C code (loaded into R with dyn.load
or library
), worked on by other C code, and destroyed by C code.
In between the calls to C, the "externalptr"
object
can be passed around in R like any other R object.
This page gives a simple example. The C code for the example is in the file
and the R code for the example is in the file
Download both files. Compile a shared library using the unix command (I explain running this example for unix or linux only, if you are on Windows, you will have to figure out the Windows equivalent from the Writing R Extensions book)
R CMD SHLIB blob.cThis should produce a shared library that I will assume is called
blob.so
(on some unices it would be called blob.sl
).
Now start R and load both bits of code with the R commands
dyn.load("blob.so") source("blob.R")
And now we are ready to try it out. The R command
fred <- blob(10)
creates a blob of 10 random numbers. If you print fred
,
though, you won't see those random numbers. R will only tell you that
fred
is an object of class "externalptr"
.
To see what is in the blob, we need to feed the "externalptr"
object back to C with
blub(fred)
We can pass this pointer around.
sally <- fred rm(fred) blub(sally)
When (if ever) we remove the last pointer
rm(sally)
R may garbage collect the pointer, and when that happens the memory used for the blob will be reclaimed. To see that we print something when the garbage collector is called.
fred <- blob(20, blather = TRUE) rm(fred) invisible(gc())The output
finalizer ran
is printed
by code in blob.c
when the memory for the blob is freed.