[Rd] Problem with new("externalptr")
Luke Tierney
luke at stat.uiowa.edu
Wed Jan 30 02:09:56 CET 2008
On Tue, 29 Jan 2008, Herve Pages wrote:
> Hi again,
>
> Here is an example of an annoyance that I think is directly related to the
> problem with new("externalptr"). When you try to extend the "externalptr" class:
You don't wnat to do that for the same reason you don't want to do it
with environments: Like environment external pointers are reference
objects, so things like unclass and other attribute changes end up
being destructive. Create the thing you want as a list wrapper around
the external pointer. You'll be a lot happier with the result in the
long run.
luke
>
> > setClass("ExternalInteger", contains="externalptr")
> [1] "ExternalInteger"
>
> then every call to new("ExternalInteger") will return the same instance too.
>
> I've tried to define an "initialize" method for "ExternalInteger" objects, but,
> whatever I do, I end up with the same "ExternalInteger" instance. So in the end
> I had to define the "ExternalInteger" class this way:
>
> > setClass("ExternalInteger", representation(xp="externalptr"))
>
> even if I'd really like to be able to use the "is a" semantic and not the "has a"
> semantic.
>
> Then I use my xp_new() C routine (see previous post) for initializing the xp slot:
>
> setMethod("initialize", "ExternalInteger",
> function(.Object, ...)
> {
> .Object at xp <- .Call("xp_new")
> ...
> .Object
> }
> )
>
> Then everytime I need to pass an "ExternalInteger" instance x to a C routine,
> I need to perform one extra step to reach the externalptr (need to pass x at xp to
> the routine instead of x itself).
>
> So unfortunately, things are quite ugly and more painful than necessary.
>
> Thanks,
> H.
>
>
> Herve Pages wrote:
>> Hi,
>>
>> It seems that new("externalptr") is always returning the same instance, and
>> not a new one as one would expect from a call to new(). Of course this is hard
>> to observe:
>>
>> > new("externalptr")
>> <pointer: (nil)>
>> > new("externalptr")
>> <pointer: (nil)>
>>
>> since not a lot of details are displayed.
>>
>> For example, it's easy to see that 2 consecutive calls to new("environment")
>> create different instances:
>>
>> > new("environment")
>> <environment: 0xc89d10>
>> > new("environment")
>> <environment: 0xc51248>
>>
>> But for new("externalptr"), I had to use the following C routine:
>>
>> SEXP sexp_address(SEXP s)
>> {
>> SEXP ans;
>> char buf[40];
>>
>> snprintf(buf, sizeof(buf), "%p", s);
>> PROTECT(ans = NEW_CHARACTER(1));
>> SET_STRING_ELT(ans, 0, mkChar(buf));
>> UNPROTECT(1);
>> return ans;
>> }
>>
>> Then I get:
>>
>> > .Call("sexp_address", new("externalptr"))
>> [1] "0xde2ce0"
>> > .Call("sexp_address", new("externalptr"))
>> [1] "0xde2ce0"
>>
>> Isn't that wrong?
>>
>> I worked around this problem by writing the following C routine:
>>
>> SEXP xp_new()
>> {
>> return R_MakeExternalPtr(NULL, R_NilValue, R_NilValue);
>> }
>>
>> so I can create new "externalptr" instances from R with:
>>
>> .Call("xp_new")
>>
>> I understand that there is not much you can do from R with an "externalptr"
>> instance and that you will have to manipulate them at the C level anyway.
>> But since new("externalptr") exists and seems to work, wouldn't that be
>> better if it was really creating a new instance at each call?
>>
>> Thanks!
>> H.
>>
>> ______________________________________________
>> 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
>
--
Luke Tierney
Chair, Statistics and Actuarial Science
Ralph E. Wareham Professor of Mathematical Sciences
University of Iowa Phone: 319-335-3386
Department of Statistics and Fax: 319-335-3017
Actuarial Science
241 Schaeffer Hall email: luke at stat.uiowa.edu
Iowa City, IA 52242 WWW: http://www.stat.uiowa.edu
More information about the R-devel
mailing list