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.