From dsamperi at DecisionSynergy.com  Thu Jun 22 18:04:25 2006
From: dsamperi at DecisionSynergy.com (Dominick Samperi)
Date: Thu, 22 Jun 2006 12:04:25 -0400
Subject: [Rd] .Call and data frames
In-Reply-To: <449A7F02.4080702@cimr.cam.ac.uk>
References: <449A25A8.1070108@DecisionSynergy.com>
	<449A78D2.8000602@cimr.cam.ac.uk> <449A7F02.4080702@cimr.cam.ac.uk>
Message-ID: <449ABF89.7080604@DecisionSynergy.com>

Thanks for the tips,

This seems to work:
First test for isReal and isInteger.
If they fail, assume character/factor, and

PROECT(colData = coerceVector(colData,INTSXP); // Not STRSXP
SEXP names = getAttrib(colData, R_LevelsSymbol);
// names now contains the string names I was looking for.

ds

Hin-Tak Leung wrote:
> Hin-Tak Leung wrote:
>> I think you want
>>         else if (TYPEOF(colData) == STRSXP)
>> ... instead.
>>
>> I don't know if this will convert from factors to string's,
>> but somewhere it probably involves something like this:
>>      PROTECT(colData = coerceVector(colData, STRSXP));
>
> FWIW, a factor consists of all these things internally:
> (1) TYPEOF(colData)  is INTSXP
> (2) attr(colData, "levels") exists and is a STRSXP type
> (string representation for the levels).
> (3) class(colData) = "factor"
>
> if coerVector() doesn't do it, you can test for (3) in your C code,
> and use the integer vector in (1) to index into the string vector in (2)
> to regenerate the string vector manually.
>
> Not all of this is correct, just an idea:
>
> class = getAttrib(colData, R_ClassSymbol);
> ...
> if (.../* do some test on class */...)
> {
>     levels = getAttrib(colData, "levels");
>     PROTECT(back_to_str = allocVector(STRSXP, LENGTH(colData));
>     for(int i = 0; i < LENGTH=(colData) ; i++)
>     {
>       SET_STRING_ELT(back_to_str, i,
>           mkChar(STRING_ELT(levels, INTEGER(colData)[i])));
>     }
> }
>
>>
>> Dominick Samperi wrote:
>>> Hello,
>>>
>>> I'm trying to fetch a data frame through the C API,
>>> and have no problem doing this when all columns
>>> are numbers, but when there is a column of
>>> strings I have a problem. On the C-side the
>>> function looks like:
>>> SEXP myfunc(SEXP df),
>>> and it is called with a dataframe from
>>> the R side with:
>>>
>>> .Call("myfunc", somedataframe)
>>>
>>> On the C side (actually C++ side) I use code
>>> like this:
>>> SEXP colnames = getAttrib(df, R_NamesSymbol)
>>> cname  = string(CHAR(STRING_ELT(colnames,i))
>>> SEXP coldata = VECTOR_ELT(df,i) (data for i-th column)
>>> if(isReal(colData))
>>>     x = REAL(colData)[j];
>>> else if(isInteger(colData))
>>>     i = INTEGER(colData)[j];
>>> else if(isString(colData))
>>>     s = CHAR(STRING_ELT(colData,j))
>>>
>>> The problem is that the last test (isString) never passes,
>>> even when I pass in a frame for which one or more cols
>>> contain character strings. When the column contains
>>> strings the isVector(colData) test passes, but no matter
>>> how I try to fetch the string data I get a seg fault. That
>>> is, forcing CHAR(STRING_ELT(colData,j)) will
>>> fault, and so will VECTOR_ELT(colData,0), even
>>> though colData passes the isVector test.
>>>
>>> Any ideas?
>>> Thanks,
>>> ds
>>>
>>> ______________________________________________
>>> 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
>
>



[Rd] .Call and data frames
Dominick Samperi