[Rcpp-devel] What is the best practice to expose a C st ructure from 3rd party library into R?
Wush Wu
wush978 at gmail.com
Tue Jul 23 18:05:11 CEST 2013
By the way, maybe you should look two files in `inst`.
The `gen_function.R` crawls http://redis.io/commands and generates the
command according to the official redis manual. You could modify
`template.R` to generate the helper functions dynamically based on the
exposed Rcpp function.
Hope it helps.
I may do something like that tomorrow evening.
>
> For now, I did something _much_ simpler still. We need single C++ source
> file. Some key features:
>
> -- no more Boost shared_ptr
> -- no more Rcpp::XPtr
> -- "empty" constructor and destructor, nothing to be done
> -- no member variables
> -- one worker function which takes string (with a redis command), runs it
> and returns the result string
> -- the worker function checks if the redis context pointer is non-NULL; in
> case it is NULL (eg first use) it creates a context
>
>
> -----------------------------------------------------------------------------
>
> #include <Rcpp.h>
> #include <hiredis/hiredis.h> // on Ubuntu file
> /usr/include/hiredis/hiredis.h
>
> // We use a static pointer which makes the variable persistent across calls
> // A more formal C++ idiom would be a singleton class, but this is simpler
> static redisContext *prc = NULL;
>
>
> // A simple and lightweight class -- without member variables
> // We could add some member variables to cache the last call, status, ...
> //
> class Redis {
>
> private:
> void checkAndInit() {
> if (prc == NULL) {
> prc = redisConnect("127.0.0.1", 6379);
> // should test for error here, could even throw() under Rcpp,
> ...
> Rcpp::Rcout << "Context created\n";
> } else {
> Rcpp::Rcout << "Reusing context\n";
> }
> }
>
> public:
> Redis() { /* Rcpp::Rcout << "In ctor\n"; */ }
> ~Redis() { /* Rcpp::Rcout << "In dtor\n"; */ }
>
> std::string execCommand(std::string cmd) {
> checkAndInit(); // important: ensure prc is set up, re-use
> if so
> redisReply *reply = static_cast<redisReply*>(redisCommand(prc,
> cmd.c_str()));
> std::string res(reply->str);
> freeReplyObject(reply);
> return(res);
> }
>
> void disconnect() {
> redisFree(prc);
> prc = NULL; // just to be on the safe side
> }
>
> // could create new functions to (re-)connect with given host and port
> etc pp
> };
>
>
> -----------------------------------------------------------------------------
>
> Couple this with a simple function (which is so simple that I wrote it
> "straight" without even Rcpp attributes. One string in, one string out:
>
>
>
> -----------------------------------------------------------------------------
> // for now, single worker function
> extern "C" SEXP execRedisCommand(SEXP p) {
> Redis redis;
> std::string txt = Rcpp::as<std::string>(p);
> std::string res = redis.execCommand(txt);
> return Rcpp::wrap(res);
> }
>
> -----------------------------------------------------------------------------
>
>
> (We could create a second function to close redis and call disconnect();
> and we could 'getter' function for the state variables inside the context.)
>
> This function is then used by a single R function:
>
>
> -----------------------------------------------------------------------------
> ## minimal R interface to redis using the hiredis library
> redis <- function(cmd) {
> ## some sanity checking on cmd would be nice too...
> .Call("execRedisCommand", cmd, package="Rhiredis")
> }
>
> -----------------------------------------------------------------------------
>
> And that is all. I added a simple tester:
>
> edd at don:~/git/Rhiredis$ Rscript tests/simpleRedisClient.R
> Context created
> [1] "PONG"
> Reusing context
> [1] "PONG"
> Reusing context
> [1] "PONG"
> Reusing context
> [1] "OK"
> Reusing context
> [1] "42"
> edd at don:~/git/Rhiredis$
>
> As you can see from the verbose text from checkAndInit(), we only need to
> create the redis instance once.
>
> I may still turn this into something based on Rcpp modules. Maybe tomorrow.
>
> The code is for now in a quick fork of your Rhiredis in my github account.
>
> Hope this helps, Dirk
>
>
> --
> Dirk Eddelbuettel | edd at debian.org | http://dirk.eddelbuettel.com
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.r-forge.r-project.org/pipermail/rcpp-devel/attachments/20130724/a778849b/attachment-0001.html>
More information about the Rcpp-devel
mailing list