Extract long[] from R object
I'm trying to make a wrapper for some C-based sparse-matrix-handling code (see previous question). In order to call the workhorse C function, I need to create a structure that looks like this:
struct smat {
long rows;
long cols;
long vals; /* Total non-zero entries. */
long *pointr; /* For each col (plus 1), index of first non-zero entry. */
long *rowind; /* For each nz entry, the row ind开发者_运维知识库ex. */
double *value; /* For each nz entry, the value. */
};
These correspond nicely to the slots in a dgCMatrix
sparse matrix. So ideally I'd just point to the internal arrays in the dgCMatrix
(after verifying that the C function won't twiddle with the data [which I haven't done yet]).
For *value
, it looks like I'll be able to use REALSXP
or something to get a double[]
as desired. But for *pointr
and *rowind
, I'm not sure the best way to get at an appropriate array. Will I need to loop through the entries and copy them to new arrays, casting as I go? Or can Rcpp
provide some sugar here? This is the first time I've really used Rcpp much and I'm not well-versed in it yet.
Thanks.
Edit: I'm also having some linking trouble that I don't understand:
Error in dyn.load(libLFile) :
unable to load shared object '/var/folders/TL/TL+wXnanH5uhWm4RtUrrjE+++TM/-Tmp-//RtmpAA9upc/file2d4606aa.so':
dlopen(/var/folders/TL/TL+wXnanH5uhWm4RtUrrjE+++TM/-Tmp-//RtmpAA9upc/file2d4606aa.so, 6): Symbol not found: __Z8svdLAS2AP4smatl
Referenced from: /var/folders/TL/TL+wXnanH5uhWm4RtUrrjE+++TM/-Tmp-//RtmpAA9upc/file2d4606aa.so
Expected in: flat namespace
in /var/folders/TL/TL+wXnanH5uhWm4RtUrrjE+++TM/-Tmp-//RtmpAA9upc/file2d4606aa.so
Do I need to be creating my library with some special compilation flags?
Edit 2: it looks like my libargs
parameter has no effect, so libsvd
symbols never make it into the library. I can find no way to include libraries using cxxfunction()
- here's what I'd tried, but the extra parameters (wishful-thinkingly-borrowed from cfunction()
) are silently gobbled up:
fn <- cxxfunction(sig=c(nrow="integer", mi="long", mp="long", mx="numeric"),
body=code,
includes="#include <svdlib.h>\n",
cppargs="-I/Users/u0048513/Downloads/SVDLIBC",
libargs="-L/Users/u0048513/Downloads/SVDLIBC -lsvd",
plugin="Rcpp",
verbose=TRUE)
I feel like I'm going about this whole process wrong, since nothing's working. Anyone kick me in the right direction?
I decided to also post a query on the Rcpp-devel mailing list, and got some good advice & help from Dirk and Doug:
http://lists.r-forge.r-project.org/pipermail/rcpp-devel/2011-February/001851.html
I'm still not super-facile with this stuff, but getting there. =)
I've done something similar for a [R]-Smalltalk-interface last year and went about it more generic to be able to pass all data back-and-forth by using byte-arrays:
In C i have:
DLLIMPORT void getLengthOfNextMessage(byte* a);
DLLIMPORT void getNextMessage(byte* a);
In R:
getLengthOfNextMessage <- function() {
tmp1 <- as.raw(rep(0,4))
tmp2<-.C("getLengthOfNextMessage", tmp1)
return(bvToInt(tmp2))
}
receiveMessage <- function() {
#if(getNumberOfMessages()==0) {
# print("error: no messages")
# return();
#}
tmp1<-as.raw(rep(0, getLengthOfNextMessage()+getSizeOfMessages()))
tmp2<-.C("getNextMessage", tmp1)
msg<-as.raw(tmp2[[1]])
print(":::confirm received")
print(bvToInt(msg[13:16]))
# confirmReceived(bvToInt(msg[13:16]))
return(msg)
}
I have commented-out the use of the functions getNumberOfMessages() and confirmReceived() which are specific to the problem i had to solve (multiple back-and-forth communication). Essentially, the code uses the argument byte-array to transfer the information, first the 4-byte-long length-info, then the actual data. This seems less elegant (even to me) than to use structs, but i found it to be more generic and i can hook into any dll, transfering any datatype.
精彩评论