Proposal for an R Connections API

Connections are not yet exposed to R package writers and those embedding R into other software. This patch to R version 2.5.0 r39773:

http://biostat.mc.vanderbilt.edu/twiki/pub/Main/RApacheProject/Conn-patch-R-devel-r39795.patch

implements one, and the latest Cairo package here:

http://www.rforge.net/Cairo/files

implements it.

Here’s what I’ve tested so far:

library(Cairo) # from the above tarball
x <- gzfile("plot.png.gz","w")
Cairo(file=x)
plot(cars)
dev.off()
flush(x) # need this for some reason
close(x)

Also, this RApache handler works:

library('Cairo')
rplot <- function(r)
{
    apache.set_content_type(r,"image/png")
    Cairo(file=stdout())
    plot(runif(100),rnorm(100),main="Random")
    dev.off()
    OK
}

and this is a patched version of RApache:

http://biostat.mc.vanderbilt.edu/twiki/pub/Main/RApacheProject/rapache-with-conn-patch-r224.tgz

Requests have been made for this on the R devel mailing list and are documented here:

https://stat.ethz.ch/pipermail/r-devel/2006-October/039681.html FIXME https://stat.ethz.ch/pipermail/r-devel/2006-October/039697.html FIXME https://stat.ethz.ch/pipermail/r-devel/2006-October/039699.html FIXME

[ If you know of others please add to the above ]

The API

Developers wanting to call functions from the API will include the R_ext/RConn.h header file that declares the Rconn struct and the public functions:

typedef struct Rconn  *Rconnection;
 
struct Rconn {
    char* class;
    char* description;
    char mode[5];
    Rboolean text, isopen, incomplete, canread, canwrite, canseek, blocking,
    isGzcon;
    Rboolean (*open)(struct Rconn *);
    void (*close)(struct Rconn *); /* routine closing after auto open */
    void (*destroy)(struct Rconn *); /* when closing connection */
    int (*vfprintf)(struct Rconn *, const char *, va_list);
    int (*fgetc)(struct Rconn *);
    int (*fgetc_internal)(struct Rconn *);
/*    int (*ungetc)(int c, struct Rconn *); */
    double (*seek)(struct Rconn *, double, int, int);
    void (*truncate)(struct Rconn *);
    int (*fflush)(struct Rconn *);
    size_t (*read)(void *, size_t, size_t, struct Rconn *);
    size_t (*write)(const void *, size_t, size_t, struct Rconn *);
/*    void (*onerror)(struct Rconn *); */
    int nPushBack, posPushBack; /* number of lines, position on top line */
    char **PushBack;
    int save, save2;
    /* unsigned char encoding[256];*/
    char encname[101];
    /* will be iconv_t, which is a pointer. NULL if not in use */
    void *inconv, *outconv;
    /* The idea here is that no MBCS char will ever not fit */
    char iconvbuff[25], oconvbuff[50], *next, init_out[25];
    short navail, inavail;
    Rboolean EOF_signalled;
    void *private;
};
 
int R_RegisterStdinConnection(SEXP scon);
int R_RegisterStdoutConnection(SEXP scon);
int R_RegisterStderrConnection(SEXP scon);
SEXP R_NewConnection(char *class, char *description, char *mode,
        Rconnection *con);
Rconnection R_GetConnection(Rconnection ucon, int idx);
void R_CloseConnection(int idx);
int R_VfprintfConnection(int idx, const char *format, va_list ap);
int R_FgetcConnection(int idx);
double R_SeekConnection(int idx, double where, int origin, int rw);
void R_TruncateConnection(int idx);
int R_FlushConnection(int idx);
size_t R_ReadConnection(int idx, void *buf, size_t size, size_t n);
size_t R_WriteConnection(int idx, const void *buf, size_t size, size_t n);
size_t R_WriteRConnection(Rconnection con, void *buf, size_t n);

R_NewConnection

SEXP R_NewConnection(char *class, char *description, char *mode, Rconnection *con)

Arguments

  • class: a character string defining the subclass; connection is the parent class. I presume there are some S3 methods that will dispatch on these.
  • description: a character string definition. merely for informational purposes.
  • mode: character string containt a combination of ‘r’ and ‘w’ for setting the struct member canread and canwrite resp.
  • con: a pointer to an Rconnection, which is a typedefed pointer itself. this must be set to the address of a valid Rconnection so that it can be passed back to the caller.

Return Value

An SEXP which is an integer vector of length one with the class attribute set to class and connection. This can be returned back to R code.

Example

Rconnection con;
SEXP scon;
 
scon = R_NewConnection("foopipe","pipe data to foo","w",&con);
scon->text = FALSE; /*stuff binary data to foo*/
 
/* foopipe_vfprintf must be declared like struct rconn's vfprintf member */
scon->vfprintf = foopipe_vfprintf; 
 
/* same for foopipe_write */
scon->write = foopipe_write;

R_RegisterStdoutConnection, R_RegisterStderrConnection, R_RegisterStdinConnection

int R_RegisterStdoutConnection(SEXP scon);
int R_RegisterStderrConnection(SEXP scon);
int R_RegisterStdinConnection(SEXP scon);

Arguments

Return Value

Returns 0 on success and -1 on failure. (Is this standard?)

R_WriteConnection

size_t R_WriteConnection(int idx, const void *buf, size_t size, size_t n)

Arguments

  • idx: integer value, always the result of a call to asInteger() on a valid connection SEXP, which begs the question, should it be changed to such?
  • buf: pointer to stuff to write
  • size: size of the items to write
  • n: number of items to write

This call is similar to the libc call fwrite, so buf must be size*n bytes long.

Return Value

The number of items written.

Example

if (R_WriteConnection(asInteger(scon),buf,1024,1) == 1){
    /* Success */
} else {
    /* Write error occured */
}

R_VfprintfConnection

int R_VfprintfConnection(int idx, const char *format, va_list ap)

Arguments

  • idx: integer value, always the result of a call to asInteger() on a valid connection SEXP.
  • format: string defining how to formout output, just like printf() argument.
  • ap: pointer to a variable argument list. do a man on vprintf for more info.

Return Value

The number of characters printed, not including the trailing NULL byte.

R_ReadConnection

size_t R_ReadConnection(int idx, void *buf, size_t size, size_t n)

Arguments

  • idx: integer value, always the result of a call to asInteger() on a valid connection SEXP.
  • buf: pointer to place the stuff read.
  • size: size of the items to read
  • n: number of items to read

This call is similar to the libc call fread, so buf must be size*n bytes long.

Return Value

The number of items written.

R_FgetcConnection

int R_FgetcConnection(int idx)

Arguments

  • idx: integer value, always the result of a call to asInteger() on a valid connection SEXP.

Return Value

The character read as an unsigned char cast to an int? I’m getting this from the fgetc man page...

R_SeekConnection

double R_SeekConnection(int idx, double where, int origin, int rw)

Arguments

  • idx: integer value, always the result of a call to asInteger() on a valid connection SEXP.
  • where: this is the same as the offset argument in fseek, and is relative to origin. man fseek for more details.
  • origin: 1 means SEEK_SET, 2 means SEEK_CUR, 3 means SEEK_END
  • rw: 1 means we’re seeking on the read-part of the connection, and 2 means we’re seeking on the write-part of the connection ?

Return Value

The position within the connection

R_TruncateConnection

void R_TruncateConnection(int idx)

Arguments

  • idx: integer value, always the result of a call to asInteger() on a valid connection SEXP.

Return Value

None

R_FlushConnection

int R_FlushConnection(int idx)

Arguments

  • idx: integer value, always the result of a call to asInteger() on a valid connection SEXP.

Return Value

Upon successful completion 0 is returned, otherwise EOF.

R_CloseConnection

void R_CloseConnection(int idx)

Arguments

  • idx: integer value, always the result of a call to asInteger() on a valid connection SEXP.

Return Value

None

 
developers/r_connections_api.txt · Last modified: 2010/06/16 by biostatmatt
 
Recent changes RSS feed R Wiki powered by Driven by DokuWiki and optimized for Firefox Creative Commons License