Jens Oehlschlägel
2003-Oct-31 12:57 UTC
[R] How to grow an R object from C (.Call Interface)
What is the best way to grow an R return object in writing a C function using the Rdefines.h macros. In my application, the final size of the return object is not known during construction. My understanding is that each time I grow an R object I have to use PROTECT() again, probably before UNPROTECTing the smaller version. However, due to the stack character of the PROTECT mechanism, UNPROTECT would not work to remove the smaller one, after the bigger has been protected. Is this an indication to use UNPROTECT_PTR ? Or is another approach recommended? May be the solution to this is worth a sentence in "Wrtiting R Extensions". Thanks for any help Jens Oehlschl?gel -- NEU F?R ALLE - GMX MediaCenter - f?r Fotos, Musik, Dateien... Fotoalbum, File Sharing, MMS, Multimedia-Gru?, GMX FotoService Jetzt kostenlos anmelden unter http://www.gmx.net +++ GMX - die erste Adresse f?r Mail, Message, More! +++
Prof Brian Ripley
2003-Oct-31 13:17 UTC
[R] How to grow an R object from C (.Call Interface)
I think the solution is PROTECT_WITH_INDEX. From the Rinternals.h file /* We sometimes need to coerce a protected value and place the new coerced value under protection. For these cases PROTECT_WITH_INDEX saves an index of the protection location that can be used to replace the protected value using REPROTECT. */ typedef int PROTECT_INDEX; #define PROTECT_WITH_INDEX(x,i) R_ProtectWithIndex(x,i) #define REPROTECT(x,i) R_Reprotect(x,i) You can see examples in dataentry.c, optim.c and elsewhere. I agree that should be mentioned in R-exts. On Fri, 31 Oct 2003, Jens Oehlschl?gel wrote:> > What is the best way to grow an R return object in writing a C function > using the Rdefines.h macros. > In my application, the final size of the return object is not known during > construction. My understanding is that each time I grow an R object I have to > use PROTECT() again, probably before UNPROTECTing the smaller version. > However, due to the stack character of the PROTECT mechanism, UNPROTECT would not > work to remove the smaller one, after the bigger has been protected. Is this > an indication to use UNPROTECT_PTR ? Or is another approach recommended? > > May be the solution to this is worth a sentence in "Wrtiting R Extensions". > > Thanks for any help > > > Jens Oehlschl?gel > >-- Brian D. Ripley, ripley at stats.ox.ac.uk Professor of Applied Statistics, http://www.stats.ox.ac.uk/~ripley/ University of Oxford, Tel: +44 1865 272861 (self) 1 South Parks Road, +44 1865 272866 (PA) Oxford OX1 3TG, UK Fax: +44 1865 272595
"Jens Oehlschl?gel" <joehl at gmx.de> writes:> What is the best way to grow an R return object in writing a C function > using the Rdefines.h macros. > In my application, the final size of the return object is not known during > construction. My understanding is that each time I grow an R object I have to > use PROTECT() again, probably before UNPROTECTing the smaller version. > However, due to the stack character of the PROTECT mechanism, UNPROTECT would not > work to remove the smaller one, after the bigger has been protected. Is this > an indication to use UNPROTECT_PTR ? Or is another approach recommended? > > May be the solution to this is worth a sentence in "Wrtiting R Extensions". > > Thanks for any helpIt depends on the kind of object, I'll assume we're talking vector objects here. If you're *extending* an existing object (the new object becomes part of the old object) matters are quite different. I think you are looking for the PROTECT_WITH_INDEX and REPROTECT mechanism that Luke added (I almost said "recently", but it was in fact three years ago!). If that is not in the manual, it should be. UNPROTECT_PTR is older and solves a similar problem, but where the routine that unprotects is not the same as the one that protects (this happens a lot in the parser code) and you cannot be sure that it is the top item that needs to be removed. UNPROTECT_PTR works by searching the stack for the pointer, pulling the record out of the stack, and dropping every stack element on top of it. In contrast REPROTECT knows which record to extract and just changes the pointer value in it. I.e. UNPROTECT_PTR is potentially much less efficient, although I don't think there are practical cases where more than an handful of items have been pushed on the stack (the usual cases are zero or one). Also remember not to call any routine that could trigger a garbage collection while you need access to both the old and the new extended object. So, allocate, copy, reprotect, and *then* start computing new entries. -- O__ ---- Peter Dalgaard Blegdamsvej 3 c/ /'_ --- Dept. of Biostatistics 2200 Cph. N (*) \(*) -- University of Copenhagen Denmark Ph: (+45) 35327918 ~~~~~~~~~~ - (p.dalgaard at biostat.ku.dk) FAX: (+45) 35327907