Recently I've been experimenting with Rcpp (inline) to generate DLLs that perform various tasks on supplied R inputs. I'd like to be able to debug the code in these DLLs line by line, given a specific set of R inputs. (I'm working under Windows.)
To illustrate, let's consider a specific example that anybody should be able to run...
The code below is a really simple cxxfunction which simply doubles the input vector. Note however that there's an additional variable myvar
that changes value a few times but doesn't affect the output - this has been added so that we'll be able to see when the debugging process is running correctly.
library(inline)
library(Rcpp)
f0 <- cxxfunction(signature(a="numeric"), plugin="Rcpp", body='
Rcpp::NumericVector xa(a);
int myvar = 19;
int na = xa.size();
myvar = 27;
Rcpp::NumericVector out1(na);
for(int i=0; i < na; i++) {
out1[i] = 2*xa[i];
myvar++;
}
myvar = 101;
return(Rcpp::List::create( _["out1"] = out1));
')
After we run the above, typing the command
getLoadedDLLs()
brings up a list of DLLs in the R session. The last one listed should be the DLL created by the above process - it has a random temporary name, which in my case is
file7e61645c
The "Filename" column shows that cxxfunction has put this DLL in the location tempdir()
, which for me is currently
C:/Users/TimP/AppData/Local/Temp/RtmpXuxtpa/file7e61645c.dll
Now, the obvious way to call the DLL is via f0
, as follows
> f0(c(-7,0.7,77))
$out1
[1] -14.0 1.4 154.0
But we can of course also call the DLL directly by name using the .Call
command:
> .Call("file7e61645c",c(-7,0.7,77))
$out1
[1] -14.0 1.4 154.0
So I've reached the point where I'm calling a standalone DLL directly with R input (here, the vector c(-7,0.7,77)
), and having it return the answer correctly to R.
What I really need, though, is a facility for line-by-line debugging (using gdb, I presume) that will allow me to observe the value of myvar
being set to 19, 27, 28, 29, 30, and finally 101 as the code progresses. The example above is deliberately set up so that calling the DLL tells us nothing about myvar.
To clarify, the "win condition" here is being able to observe myvar changing (seeing the value myvar=19 would be the first step!) without adding anything else to the body of the code. This obviously may require changes to the way in which the code is compiled (are there debugging mode settings to turn on?), or the way R is called - but I don't know where to begin. As noted above, all of this is Windows-based.
Final note: In my experiments, I actually made some minor modifications to a copy of cxxfunction so that the output DLL - and the code within it - receives a user-defined name and sits in a user-defined directory, rather than a temporary name and location. But this doesn't affect the essence of the question. I mention this just to emphasise that it should be fairly easy to alter the compilation settings if someone gives me a nudge :)
For completeness, setting verbose=TRUE in the original cxxfunction call above shows the compilation argument to be of the following form:
C:/R/R-2.13.2/bin/i386/R CMD SHLIB file7e61645c.cpp 2> file7e61645c.cpp.err.txt
g++ -I"C:/R/R-213~1.2/include" -I"C:/R/R-2.13.2/library/Rcpp/include" -O2 -Wall -c file7e61645c.cpp -o file7e61645c.o
g++ -shared -s -static-libgcc -o file7e61645c.dll tmp.def file7e61645c.o C:/R/R-2.13.2/library/Rcpp/lib/i386/libRcpp.a -LC:/R/R-213~1.2/bin/i386 -lR
My adapted version has a compilation argument identical to the above, except that the string "file7e61645c" is replaced everywhere by the user's choice of name (e.g. "testdll") and the relevant files copied over to a more permanent location.
Thanks in advance for your help guys :)