From sfalcon at fhcrc.org  Tue May 15 01:01:32 2007
From: sfalcon at fhcrc.org (Seth Falcon)
Date: Mon, 14 May 2007 16:01:32 -0700
Subject: [Rd] Best Practise
In-Reply-To: <op.tsa5koddcsmg07@localhost.localdomain> (Tom McCallum's message
	of "Mon, 14 May 2007 09:23:02 +0100")
References: <op.tsa5koddcsmg07@localhost.localdomain>
Message-ID: <m2646v2enn.fsf@ziti.local>

Tom McCallum <termcc at googlemail.com> writes:

> Hello,
>
>
> Just a quick question on best practise.  I am converting quite a bit of  
> legacy C code into R packages and have the following situation:
>
> (1) Legacy object with a double* array in, all over code so don't want to  
> change any more than I have to.
>
> (2) Do something like:
> 	SEXP arrayToPassToR;
> 	PROTECT( arrayToPassToR = allocVector( REALSXP, n ) );
> 	for(i=0; i < n; i++) {
> 		REAL(arrayToPassToR)[i] = oldCarray[i];   <----  very slow way to copy  
> data, can I use memcpy/pointer assignment here to remove the loop without  
> running into garbage collector?

You can use memcpy and that should be no different semantically from
the loop.  You cannot reassign the pointer.

Perhaps it is possible to refactor the part of your legacy code that
allocates the vector to begin with?  Then you can use R's allocVector
and send the pointer to the alloc'd vector off to your code.

> (3) Have made it to call back to an R function which returns a new /  
> different SEXP double array.
> 	returnValueFromR = Test_tryEval(...);
> (4) Copy back to oldCArray
> 	for(i=0; i < n; i++) {
> 		oldCarray[i] = REAL(returnValueFromR)[i]; <--- can I use memcpy/pointer  
> assignment here to remove loop?
> 	}
> 	UNPROTECT(1);

Depending on how you will use oldCarray, you may not need a copy at
all.  If you have a function that takes a double* then you can pass in
REAL(returnValueFromR).

> I have done the long winded copy as I am a bit paranoid about the garbage  
> collection.  My question is is it legitimate to do the following
>
> 	double* oldCArray = REAL(arrayToPassToR);
> 	UNPROTECT(1); // where the 1 would remove protection from arrayToPassToR  
> and potential garbage collection
> 	-- assume arrayToPassToR was garbage collected by R --
> 	Rprintf("%f", oldCArray[0]);
>
> because if arrayToPassToR is garbage collected then oldCArray will cause a  
> SEGFAULT when it is accessed afterwards, won't it?

If you UNPROTECT arrayToPassToR, then the next time R's gc runs
oldCArray will be invalid.

It isn't clear to me from your post what exactly you are trying to do
(and your subject line is confusing, this isn't a best practice
question IMO, but a how do I use R objects in C question).

Perhaps the above hints will get you going.  I would recommend reading
over the relevant sections of the Writing R Extensions manual and the
R internals manual.

+ seth

-- 
Seth Falcon | Computational Biology | Fred Hutchinson Cancer Research Center
http://bioconductor.org



[Rd] Best Practise
Seth Falcon