This is discussed in the "Writing R Extensions" manual section 5.9.10: Named objects and copying.
.Call does not copy its arguments and it is not safe to modify them, as you have found, since multiple symbols may refer to the same object. If you are going to modify an argument to .Call you should take a deep copy with "duplicate" first, and your function should return the modified copy. It is probably also worth mentioning Rcpp, which provides a friendlier interface to R than the C API. In Rcpp you use clone() to force a deep copy. Martyn On Tue, 2016-04-05 at 15:38 +0000, Thorsten R wrote: > Hi All, > > i have a problem in understanding what the assignment operator '<- > ' really is doing. > If i create two numeric arrays in R and copy one into the other with > '<-' and > afterwards change one array by calling a C function, both arrays are > changed! > > The problem I am facing can easily be seen in the following example: > (The following R code and the C function is attached and the C > function can be compiled with R CMD SHLIB test.c.) > > First include the c function: > dyn.load("test.so") > > Let's start with 2 arrays: > a <- rep(0, 5) > b <- rep(1, 5) > > Now print the memory addresses: > print(sprintf("a: %s b: %s", tracemem(a), tracemem(b) )) > [1] "a: <0x29d34e0> b: <0x29946e0>" > > oky, they are different! Now copy a into b and print again the > addresses: > b <- a > print(sprintf("a: %s b: %s", tracemem(a), tracemem(b) )) > [1] "a: <0x29d34e0> b: <0x29d34e0>" > > Ugh they are the same. If I now call my C function, which writes > 0,1,2,3,4 into an array of 5 doubles, > of course 'both' arrays are changed: > .Call("test", b) > print( cbind(a,b) ) > a b > [1,] 0 0 > [2,] 1 1 > [3,] 2 2 > [4,] 3 3 > [5,] 4 4 > > > If i just change one element of b instead of calling the c function, > then a full copy of b is made: > a <- rep(0, 5) > b <- rep(1, 5) > print(sprintf("a: %s b: %s", tracemem(a), tracemem(b) )) > [1] "a: <0x2994b58> b: <0x2912ff8>" > > b <- a > print(sprintf("a: %s b: %s", tracemem(a), tracemem(b) )) > [1] "a: <0x2994b58> b: <0x2994b58>" > > b[1] <- 5 > print(sprintf("a: %s b: %s", tracemem(a), tracemem(b) )) > "a: <0x2994b58> b: <0x29134d8>" > > print( cbind(a,b) ) > a b > [1,] 0 5 > [2,] 0 0 > [3,] 0 0 > [4,] 0 0 > [5,] 0 0 > > > So what is happening here? What is the 'right' way to ensure a deep > copy before using Call? > I am currently using a for loop and copy every single element. > > Thanks! > > ______________________________________________ > R-devel@r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel----------------------------------------------------------------------- This message and its attachments are strictly confidenti...{{dropped:8}} ______________________________________________ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel