Hi all, I've been writing a package and I've run into a problem that I'm unsure how to solve. I am looking to pass a C++ class object to R so that it may be passed back to another C++ function later on to be used. I'm quite new to R and this is my first time writing a package, so I hope you can bear with me. The following is how I create the class and use R_MakeExternalPtr(). This occurs in a function called "soamInit": Session* sesPtr = conPtr->createSession(attributes); void* temp = session; SEXP out = R_MakeExternalPtr(temp, R_NilValue, R_NilValue); return out; The following is how I try to retrieve the class object in a different C++ function called "soamSubmit", where sesCon is the externalPtr : void* temp = R_ExternalPtrAddr(sesCon); Session* sesPtr = reinterpret_cast<Session*>(temp); The error I get when trying to run the R function is : *** caught segfault *** address 0x3, cause 'memory not mapped' Traceback: 1: .Call("soamSubmit", counter, sesCon, final.script, packages) 2: soam.Rapply(x, tester, join.method = c, njobs = 2) So it seems like a scoping problem to me, though I'm unsure how to solve it. -Jon -- View this message in context: http://www.nabble.com/Using-R_MakeExternalPtr-tf4142904.html#a11785023 Sent from the R devel mailing list archive at Nabble.com.
Jon, I suspect that you're leaving out some important details - please include your R code for inspection as the C++ code below seems ok (although you may want to show us the declarations as well). Also you may want to look into this with a debugger in case the segfault is actually in your C++ code due to some memory management issue. Cheers, Simon On Jul 25, 2007, at 11:35 AM, Jonathan Zhou wrote:> > Hi all, > > I've been writing a package and I've run into a problem that I'm > unsure how > to solve. I am looking to pass a C++ class object to R so that it > may be > passed back to another C++ function later on to be used. I'm quite > new to R > and this is my first time writing a package, so I hope you can bear > with me. > > The following is how I create the class and use R_MakeExternalPtr > (). This > occurs in a function called "soamInit": > Session* sesPtr = conPtr->createSession(attributes); > void* temp = session; > > SEXP out = R_MakeExternalPtr(temp, R_NilValue, R_NilValue); > return out; > > The following is how I try to retrieve the class object in a > different C++ > function called "soamSubmit", where sesCon is the externalPtr : > void* temp = R_ExternalPtrAddr(sesCon); > Session* sesPtr = reinterpret_cast<Session*>(temp); > > The error I get when trying to run the R function is : > *** caught segfault *** > address 0x3, cause 'memory not mapped' > > Traceback: > 1: .Call("soamSubmit", counter, sesCon, final.script, packages) > 2: soam.Rapply(x, tester, join.method = c, njobs = 2) > > So it seems like a scoping problem to me, though I'm unsure how to > solve it. > > -Jon > -- > View this message in context: http://www.nabble.com/Using- > R_MakeExternalPtr-tf4142904.html#a11785023 > Sent from the R devel mailing list archive at Nabble.com. > > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel > >
Jonathan Zhou <jonathan.zhou at utoronto.ca> writes:> Hi all, > > I've been writing a package and I've run into a problem that I'm unsure how > to solve. I am looking to pass a C++ class object to R so that it may be > passed back to another C++ function later on to be used. I'm quite new to R > and this is my first time writing a package, so I hope you can bear with me. > > The following is how I create the class and use R_MakeExternalPtr(). This > occurs in a function called "soamInit": > Session* sesPtr = conPtr->createSession(attributes); > void* temp = session;It isn't clear from your example, are you sure that temp is valid at this point?> SEXP out = R_MakeExternalPtr(temp, R_NilValue, R_NilValue);I was expecting to see: SEXP out = R_MakeExternalPtr((void *)sesPtr, R_NilValue, R_NilValue); + seth -- Seth Falcon | Computational Biology | Fred Hutchinson Cancer Research Center http://bioconductor.org
As other has commented, without the rest/full of your code it is difficult to tell... I have a few suggestions though: - it is obviously a memory-related issue. An external pointer is partly allocated by R and partly allocated by you - you need to check both parts, and their individual usages. - I think the part allocated by R is correct; you might need a few PROTECT() somewhere unrelated in "soamSubmit" as well, when you are playing R objects in C/C++... what I mean is, the external pointer may be unrelated to your problem. Jonathan Zhou wrote:> Hi all, > > I've been writing a package and I've run into a problem that I'm unsure how > to solve. I am looking to pass a C++ class object to R so that it may be > passed back to another C++ function later on to be used. I'm quite new to R > and this is my first time writing a package, so I hope you can bear with me. > > The following is how I create the class and use R_MakeExternalPtr(). This > occurs in a function called "soamInit": > Session* sesPtr = conPtr->createSession(attributes); > void* temp = session; > > SEXP out = R_MakeExternalPtr(temp, R_NilValue, R_NilValue); > return out; > > The following is how I try to retrieve the class object in a different C++ > function called "soamSubmit", where sesCon is the externalPtr : > void* temp = R_ExternalPtrAddr(sesCon); > Session* sesPtr = reinterpret_cast<Session*>(temp); > > The error I get when trying to run the R function is : > *** caught segfault *** > address 0x3, cause 'memory not mapped' > > Traceback: > 1: .Call("soamSubmit", counter, sesCon, final.script, packages) > 2: soam.Rapply(x, tester, join.method = c, njobs = 2) > > So it seems like a scoping problem to me, though I'm unsure how to solve it. > > -Jon
Hi all, Here is the R code function in where I called the two C++ and further below are the 2 C++ functions I used to create the externalptr and use it : soam.Rapply <- function (x, func, ..., join.method=cbind, njobs, batch.size=100, packages=NULL, savelist=NULL) { if(missing(njobs)) njobs <- max(1,ceiling(nrow(x)/batch.size)) if(!is.matrix(x) && !is.data.frame(x)) stop("x must be a matrix or data frame") if(njobs>1) {rowSet <- lapply(splitIndices(nrow(x), njobs), function(i) x[i, , drop = FALSE])} else {rowSet <- list(x)} sesCon <- .Call("soamInit") script <- " " fname <- tempfile(pattern = "Rsoam_data", tmpdir = getwd()) file(fname, open="w+") if(!is.null(savelist)) { dump(savelist, fname) script<-readLines(fname) } if(!is.null(packages)) for(counter in 1:length(packages)) { temp<-call("library", packages[counter], character.only=TRUE) dput(temp, fname) pack.call<-readLines(fname) script<-append(script, pack.call) } for(counter in 1:njobs) { caller <- paste("caller", counter, sep = "") soam.call<-call("dput", call("apply", X=rowSet[[counter]], MARGIN=1, FUN=func), caller) dput(soam.call, fname) soam.call<-readLines(fname) temp<-append(script, soam.call) final.script = temp[1] for(count in 2:length(temp)){ final.script<-paste(final.script, temp[count], "\n")} .Call("soamSubmit", counter, sesCon, final.script, packages) } .Call("soamGetResults", sesCon, njobs, join.method, parent.frame()) for(job in 1:njobs) { caller <- paste("result", job, sep = "") temp = dget(caller) if(job==1) {retval=temp} else {retval=join.method(retval,temp)} } .Call("soamUninit") retval } *** Here are the 2 C++ functions: extern "C" { SEXP soamInit () { // Initialize the API SoamFactory::initialize(); // Set up application specific information to be supplied to Symphony char appName[] = "SampleAppCPP"; // Set up application authentication information using the default security provider DefaultSecurityCallback securityCB("Guest", "Guest"); // Connect to the specified application ConnectionPtr conPtr = SoamFactory::connect(appName, &securityCB); // Set up session creation attributes SessionCreationAttributes attributes; attributes.setSessionName("mySession"); attributes.setSessionType("ShortRunningTasks"); attributes.setSessionFlags(SF_RECEIVE_SYNC); // Create a synchronous session Session* sesPtr = conPtr->createSession(attributes); SEXP out = R_MakeExternalPtr((void*)temp, R_NilValue, R_NilValue); return out; } } extern "C" { void soamSubmit (SEXP jobID, //job ID SEXP sesCon, //session pointer SEXP caller, //objects SEXP pack) //packages { char* savelist = CHAR(STRING_ELT(caller, 0)); string strTemp = ""; int job = INTEGER(jobID)[0]; void* temp = R_ExternalPtrAddr(sesCon); Session* sesPtr = reinterpret_cast<Session*>(temp); // Create a message MyMessage inMsg(job, /*pack,*/ savelist); // Send it TaskInputHandlePtr input = sesPtr->sendTaskInput(&inMsg); } } -- View this message in context: http://www.nabble.com/Using-R_MakeExternalPtr-tf4142904.html#a11786494 Sent from the R devel mailing list archive at Nabble.com.
On Jul 25, 2007, at 12:53 PM, Jonathan Zhou wrote:> [snip] > extern "C" > { > void soamSubmit (SEXP jobID, //job ID^^^ - this will definitely crash. All .Call functions must return SEXP, even if it is just R_NilValue; Cheers, Simon> SEXP sesCon, //session pointer > SEXP caller, //objects > SEXP pack) //packages > { > char* savelist = CHAR(STRING_ELT(caller, 0)); > string strTemp = ""; > int job = INTEGER(jobID)[0]; > > void* temp = R_ExternalPtrAddr(sesCon); > Session* sesPtr = reinterpret_cast<Session*>(temp); > > // Create a message > MyMessage inMsg(job, /*pack,*/ savelist); > > // Send it > TaskInputHandlePtr input = sesPtr->sendTaskInput(&inMsg); > } > } > -- > View this message in context: http://www.nabble.com/Using- > R_MakeExternalPtr-tf4142904.html#a11786494 > Sent from the R devel mailing list archive at Nabble.com. > > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel > >
Hi Hin-Tak, Here is the R code function in where I called the two C++ and further below are the 2 C++ functions I used to create the externalptr and use it : soam.Rapply <- function (x, func, ..., join.method=cbind, njobs, batch.size=100, packages=NULL, savelist=NULL) { if(missing(njobs)) njobs <- max(1,ceiling(nrow(x)/batch.size)) if(!is.matrix(x) && !is.data.frame(x)) stop("x must be a matrix or data frame") if(njobs>1) {rowSet <- lapply(splitIndices(nrow(x), njobs), function(i) x[i, , drop = FALSE])} else {rowSet <- list(x)} sesCon <- .Call("soamInit") script <- " " fname <- tempfile(pattern = "Rsoam_data", tmpdir = getwd()) file(fname, open="w+") if(!is.null(savelist)) { dump(savelist, fname) script<-readLines(fname) } if(!is.null(packages)) for(counter in 1:length(packages)) { temp<-call("library", packages[counter], character.only=TRUE) dput(temp, fname) pack.call<-readLines(fname) script<-append(script, pack.call) } for(counter in 1:njobs) { caller <- paste("caller", counter, sep = "") soam.call<-call("dput", call("apply", X=rowSet[[counter]], MARGIN=1, FUN=func), caller) dput(soam.call, fname) soam.call<-readLines(fname) temp<-append(script, soam.call) final.script = temp[1] for(count in 2:length(temp)){ final.script<-paste(final.script, temp[count], "\n")} .Call("soamSubmit", counter, sesCon, final.script, packages) } .Call("soamGetResults", sesCon, njobs, join.method, parent.frame()) for(job in 1:njobs) { caller <- paste("result", job, sep = "") temp = dget(caller) if(job==1) {retval=temp} else {retval=join.method(retval,temp)} } .Call("soamUninit") retval } *** Here are the 2 C++ functions: extern "C" { SEXP soamInit () { // Initialize the API SoamFactory::initialize(); // Set up application specific information to be supplied to Symphony char appName[] = "SampleAppCPP"; // Set up application authentication information using the default security provider DefaultSecurityCallback securityCB("Guest", "Guest"); // Connect to the specified application ConnectionPtr conPtr = SoamFactory::connect(appName, &securityCB); // Set up session creation attributes SessionCreationAttributes attributes; attributes.setSessionName("mySession"); attributes.setSessionType("ShortRunningTasks"); attributes.setSessionFlags(SF_RECEIVE_SYNC); // Create a synchronous session Session* sesPtr = conPtr->createSession(attributes); SEXP out = R_MakeExternalPtr((void*)temp, R_NilValue, R_NilValue); return out; } } extern "C" { void soamSubmit (SEXP jobID, //job ID SEXP sesCon, //session pointer SEXP caller, //objects SEXP pack) //packages { char* savelist = CHAR(STRING_ELT(caller, 0)); string strTemp = ""; int job = INTEGER(jobID)[0]; void* temp = R_ExternalPtrAddr(sesCon); Session* sesPtr = reinterpret_cast<Session*>(temp); // Create a message MyMessage inMsg(job, /*pack,*/ savelist); // Send it TaskInputHandlePtr input = sesPtr->sendTaskInput(&inMsg); } } -- View this message in context: http://www.nabble.com/Using-R_MakeExternalPtr-tf4142904.html#a11790985 Sent from the R devel mailing list archive at Nabble.com.