.Call setAttrib(ans,R_DimSymbol,dim); Crashes.
"wolski" <wolski at molgen.mpg.de> writes:
I want to return a matrix. The code does the R interfacing. This
version does it fine.
SEXP ans,dim;
PROTECT(ans = NEW_NUMERIC(count*2));
memcpy(NUMERIC_POINTER(ans),result,count*sizeof(double));
memcpy(&(NUMERIC_POINTER(ans)[count]),occur,count*sizeof(double));
/** PROTECT(dim=NEW_INTEGER(2));
INTEGER_POINTER(dim)[0]=2;
INTEGER_POINTER(dim)[1]=count;
setAttrib(ans,R_DimSymbol,dim);
*/
UNPROTECT(7);
If I uncomment the lines 5 to 8 than all is working fine four small
count's (tested 10,20). But if the result is an array with about
2000 entries R crashes vicious and violently with the lax comment
Process R trace trap at Wed Feb 11 13:55:45 2004
Anyone is seeiing something what I can not see?
In most cases it is easier to use allocMatrix instead of assigning a dimension attribute to a numeric vector. You could write this as SEXP ans = PROTECT(allocMatrix(REALSXP, 2, count)); memcpy(NUMERIC_POINTER(ans),result,count*sizeof(double)); memcpy(&(NUMERIC_POINTER(ans)[count]),occur,count*sizeof(double)); UNPROTECT(1); Another enhancement is use Memcpy, as in SEXP ans = PROTECT(allocMatrix(REALSXP, 2, count)); double *ansp = REAL(ans); /* same as NUMERIC_POINTER(ans) */ Memcpy(ansp, result, count); Memcpy(ansp + count, occur, count); UNPROTECT(1); Regarding your particular problem, did you happen to change the argument to UNPROTECT when you changed the code? You may be getting a stack imbalance if you change the number of PROTECTs that are executed and don't change the UNPROTECT count. This is why I generally try to write C functions with only one PROTECT in then. Because PROTECTing an object also PROTECTs all components reachable from that object I allocate other storage as components of the (PROTECT'ed) result then manipulate those components. For example, if I don't use allocMatrix I would write what you did as SEXP ans = PROTECT(NEW_NUMERIC(count * 2)); double *ansp = NUMERIC_POINTER(ans); int *dims; Memcpy(ansp, result, count); Memcpy(ansp + count, occur, count); setAttrib(ans, R_DimSymbol, NEW_INTEGER(2)); dims = INTEGER_POINTER(getAttrib(ans, R_DimSymbol)); dims[0] = 2; dims[1] = count; UNPROTECT(1); It is a matter of taste whether you prefer to assign the component then select it or to allocate the component by itself and remember to PROTECT and UNPROTECT it. Both are a bit tedious but I find the former to be less error-prone. If you look at the C sources for the new Matrix_0.6 package (in the 1.9 contributed section on CRAN) you will see that just about every C function that returns an SEXP ends with UNPROTECT(1); return ans;
Douglas Bates bates at stat.wisc.edu Statistics Department 608/262-2598 University of Wisconsin - Madison http://www.stat.wisc.edu/~bates/