[Rd] Problem with new("externalptr")
Herve Pages
hpages at fhcrc.org
Wed Jan 30 02:03:18 CET 2008
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:
> 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
>
More information about the R-devel
mailing list