From simon.urbanek at r-project.org  Tue Sep 29 19:00:05 2009
From: simon.urbanek at r-project.org (Simon Urbanek)
Date: Tue, 29 Sep 2009 13:00:05 -0400
Subject: [Rd] How do I access class slots from C?
In-Reply-To: <4AC2332F.2030108@fhcrc.org>
References: <fc212e850909290728j1f3a305bkf82db6dfcd42d8a9@mail.gmail.com>
	<2C3C1E09-AF03-4F6F-B6C4-D5D4B8CA607A@r-project.org>
	<4AC2332F.2030108@fhcrc.org>
Message-ID: <F643067A-CF9C-45D3-8745-7341A0676896@r-project.org>

MArtin,

On Sep 29, 2009, at 12:17 , Martin Morgan wrote:

> Simon Urbanek wrote:
>> Abhijit,
>> as for your subject - it's GET_SLOT,
>> but why don't you just use ParseVector and eval instead of hand- 
>> crafting C code that calls the evaluator? That latter is way more  
>> error prone and the error-handling is a nightmare (your current  
>> code is inefficient anyway so you don't gain anything).
>
> My 2 cents: constructing language calls seems much more appropriate  
> than parsing expressions when the values to be used are from  
> programming variables, as is likely the case in most real  
> applications?

Yes, but not in this case - it's all just replication of a script that  
could be evaluated with one call, there are no native objects  
involved. As soon as you start using more than one eval in the C code,  
it is very likely not the right way to go. I do agree that constructed  
expressions are useful if you have a) a very short call that cannot be  
easily done at C level or b) it involves  unassigned objects generated  
in the C code -- but neither it the case here.


> And accessing slots with GET_SLOT seems to break the (hard-won)  
> abstraction layer of S4, so better to call the R accessors (even  
> when this is inefficient computationally) especially when using  
> objects from packates whose internals you do not control.
>

Agreed, again something that could be prevented with parse + eval ;).


> One particular part of the code below
>
> PROTECT 
> (e 
> =lang4(install("c"),mkString("SBI"),mkString("SPI"),mkString("SII")));
>
> could be re-written as
>
>  SEXP x = PROTECT(NEW_CHARACTER(3));
>  SET_STRING_ELT(x, 0, mkChar("SBI"));
>  etc
>
> In the original, although the outer PROTECT is unnecessary, I wonder  
> about the mString()... calls, which are not guaranteed to be  
> evaluated in order and produce unprotected CHARSXPs (prior to being  
> protected inside lang4). I'm not really sure about the mkChar() in  
> the above, either, and whether there is an opportunity for garbage  
> collection in SET_VECTOR_ELT.
>

CHARSXPs are always protected by enclosing STRSXP and  
SET_STRING_ELT(x, i, mkChar()) is always safe. And yes, the lang4 "c"  
construct is a bad idea.

Cheers,
Simon


>
>
>> As for setWeights, you got the code wrong - if you want to mimic  
>> the R code then it's a call to the assignment "<-" - have a look at  
>> the parse result of
>> "setWeights(ewSpec) <- rep(1/nAssets, times = nAssets)":
>>  @d58774 06 LANGSXP g0c0 []
>>    @809008 01 SYMSXP g1c0 [MARK,gp=0x4000] "<-"
>>    @d59540 06 LANGSXP g0c0 []
>>      @1a1af34 01 SYMSXP g0c0 [] "setWeights"
>>      @d59498 01 SYMSXP g0c0 [] "ewSpec"
>>    @d58720 06 LANGSXP g0c0 []
>>      @814ac4 01 SYMSXP g1c0 [MARK,gp=0x4000] "rep"
>>      @d595b0 06 LANGSXP g0c0 []
>>    @80ae44 01 SYMSXP g1c0 [MARK,gp=0x4000] "/"
>>    @1bf8ce8 14 REALSXP g0c1 [] (len=1, tl=0) 1
>>    @1dbf1ac 01 SYMSXP g0c0 [MARK] "nAssets"
>>      TAG: @9450fc 01 SYMSXP g1c0 [MARK] "times"
>>      @1dbf1ac 01 SYMSXP g0c0 [MARK] "nAssets"
>> Again, I think you would be far better off just using parse  
>> instead...
>> Cheers,
>> Simon
>> PS: Your PROTECTs are way off-balance, and you don't need almost  
>> any of them - langX and listX protect all arguments
>> On Sep 29, 2009, at 10:28 , Abhijit Bera wrote:
>>> Hi
>>>
>>> I'm trying to implement something similar to the following R  
>>> snippet using
>>> C. I seem to have hit the wall on accessing class slots using C.
>>>
>>> library(fPortfolio)
>>>
>>> lppData <- 100 * LPP2005.RET[, 1:6]
>>> ewSpec <- portfolioSpec()
>>> nAssets <- ncol(lppData)
>>> setWeights(ewSpec) <- rep(1/nAssets, times = nAssets)
>>>
>>> ewPortfolio <- feasiblePortfolio(
>>>  data = lppData,
>>>  spec = ewSpec,
>>>  constraints = "LongOnly")
>>>
>>> ewSpec is an object of type Portfolio Spec which has the following  
>>> slots:
>>>
>>> model slot
>>>   type = "MV"                  a string value
>>>   optimize = "minRisk"         a string value
>>>   estimator = "covEstimator"   a function name
>>>   tailRisk = list()            a list
>>>   params =
>>>     list(alpha=0.05, a=1, ...) a list
>>> portfolio slot                   a list
>>>   weights = NULL               a numeric vector
>>>   targetReturn = NULL          a numeric value
>>>   targetRisk = NULL            a numeric value
>>>   riskFreeRate = 0             a numeric value
>>>   nFrontierPoints = 50         an integer value
>>>   status = NA)                 a integer value
>>> optim slot                       a list
>>>   solver = "solveRquadprog"    a function names
>>>   objective = NULL             function names
>>>   options = list()             a list with parameters
>>>   control = list()             a list with controls
>>>   trace = FALSE)               a logical
>>> messages slot:                   a list
>>>   list = list()                a list
>>>
>>> I want to set the weights so that I can compute a feasiblePortfolio.
>>> Unfortunately I cannot figure out how to do this from C.
>>>
>>> Here is what I wrote so far:
>>>
>>> #include <stdio.h>
>>> #include <R.h>
>>> #include <Rinternals.h>
>>> #include <Rdefines.h>
>>> #include <Rembedded.h>
>>>
>>> int main(int argc, char** argv)
>>> {
>>>
>>>   SEXP
>>> e 
>>> ,c 
>>> ,portSpec 
>>> ,portData 
>>> ,portConstr 
>>> ,portVal,portWeights,tsAssets,tsReturns,nAssets,reciprocal;
>>>   int errorOccurred,nx,ny,i,j;
>>>   double *v;
>>>   const char *x,*y;
>>>
>>>   Rf_initEmbeddedR(argc, argv);
>>>
>>>   // loading fPortfolio
>>>   PROTECT(e = lang2(install("library"), mkString("fPortfolio")));
>>>   R_tryEval(e, R_GlobalEnv, NULL);
>>>   UNPROTECT(1);
>>>
>>>
>>>   // creating a default portfolioSpec object
>>>   PROTECT(e=lang1(install("portfolioSpec")));
>>>   PROTECT(portSpec=R_tryEval(e,R_GlobalEnv, NULL));
>>>
>>>   // creating a portfolioData object
>>>
>>>
>>> PROTECT 
>>> (e 
>>> = 
>>> lang4 
>>> (install("c"),mkString("SBI"),mkString("SPI"),mkString("SII")));
>>>   PROTECT(tsAssets=R_tryEval(e,R_GlobalEnv,NULL));
>>>
>>>    
>>> PROTECT 
>>> (e=lang4(install("["),install("SWX.RET"),R_MissingArg,tsAssets));
>>>   PROTECT(tsReturns=R_tryEval(e,R_GlobalEnv,NULL));
>>>
>>>   PROTECT(e=lang3(install("*"),ScalarInteger(100),tsReturns));
>>>   PROTECT(tsReturns=R_tryEval(e,R_GlobalEnv,NULL));
>>>
>>>   PROTECT(e=lang3(install("portfolioData"),tsReturns,portSpec));
>>>   PROTECT(portData=R_tryEval(e,R_GlobalEnv,NULL));
>>>
>>> // Creating a portfolio constraints string
>>>   PROTECT(portConstr=mkString("LongOnly"));
>>>
>>> // Setting weights
>>>   PROTECT(e=lang2(install("ncol"),tsReturns));
>>>   PROTECT(nAssets=R_tryEval(e,R_GlobalEnv,NULL));
>>>
>>>   PROTECT(e=lang3(install("/"),ScalarInteger(1),nAssets));
>>>   PROTECT(reciprocal=R_tryEval(e,R_GlobalEnv,NULL));
>>>
>>>   PROTECT(e=lang3(install("rep"),reciprocal,nAssets));
>>>   PROTECT(portWeights=R_tryEval(e,R_GlobalEnv,NULL));
>>>
>>> // Right now the program crashes here. It says: Cannot find function
>>> "setWeights"
>>> // How do I set the weights? It's a standard numeric vector. I'm  
>>> confused on
>>> access class slots from C.
>>> // Not much is writted on this in the R extensions manual.
>>>
>>>   PROTECT(e=lang3(install("setWeights"),portSpec,portWeights));
>>>   PROTECT(portSpec=R_tryEval(e,R_GlobalEnv,NULL));
>>>
>>>   PROTECT(e=lang2(install("print"),portSpec));
>>>   R_tryEval(e,R_GlobalEnv,NULL);
>>>
>>>   UNPROTECT(3);
>>>
>>>   Rf_endEmbeddedR(0);
>>>
>>>   return 0;
>>> }
>>>
>>> Regards
>>> Abhijit Bera
>>>
>>>    [[alternative HTML version deleted]]
>>>
>>> ______________________________________________
>>> R-devel at r-project.org mailing list
>>> https://stat.ethz.ch/mailman/listinfo/r-devel
>>>
>>>
>> ______________________________________________
>> R-devel at r-project.org mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-devel
>
>
> -- 
> Martin Morgan
> Computational Biology / Fred Hutchinson Cancer Research Center
> 1100 Fairview Ave. N.
> PO Box 19024 Seattle, WA 98109
>
> Location: Arnold Building M1 B861
> Phone: (206) 667-2793
>
>



[Rd] How do I access class slots from C?
Simon Urbanek