[Rd] Passing externalptr to .C()

Rick Sayre whorfin at pixar.com
Thu May 17 00:30:37 CEST 2012


Thanks very much for the quick reply.

I'd like to avoid static state in the .so, which is why I'm using
the opaque pointer.  It is indeed possible to convert everything to
.Call(), but the work seems unnecessary given that it used to work
just fine and I am going out of my way to pass things with correct
type conversion and semantics.  Again, this seems like exactly the
usage externalptr was designed for, doesn't it?

It seems I can avoid the warnings by putting the externalptr in
a list:

getDeviceInfo<- function(handle) {
     .C("groovyDevice_getDeviceInfo", PACKAGE="groovyDevice",
	list(handle),	# Avoid pedantic warnings via encapsulation
	status = as.integer(0))[-1] # skip handle
}

void
groovyDevice_getDeviceInfo(SEXP *handle, int *status)
{
     groovyHandle *gh = R_ExternalPtrAddr(*handle);
     *status = GroovyStatus(gh);
}

Perhaps this will help others in the same boat in which I find myself.

Cheers

	--Rick

On 05/11/2012 03:34 PM, Duncan Murdoch wrote:
> On 12-05-11 5:20 PM, Rick Sayre wrote:
>> Greetings.
>>
>> 2.15.0 added this behavior
>> http://developer.r-project.org/blosxom.cgi/R-devel/NEWS/2012/03/29#n2012-03-29
>>
>>
>> o Passing R objects other than atomic vectors, functions, lists and
>> environments to .C() is now deprecated and will give a warning.
>> Most cases (especially NULL) are actually coding errors. NULL
>> will be disallowed in future.
>>
>>
>> This seems to make sense, except that this case includes externalptrs.
>>
>> I have quite a bit of code, designed to interface with various
>> external hardware devices, which uses this sort of idiom:
>>
>> # for example
>> getDeviceInfo<- function(handle) {
>> .C("groovyDevice_getDeviceInfo", PACKAGE="groovyDevice",
>> handle,
>> status = as.integer(0))[-1] # skip handle
>> }
>>
>> where "handle" was the result of a .Call to a routine which
>> returned a SEXP which was the result of a R_MakeExternalPtr() call
>>
>> The "c" routine looked like:
>> void
>> groovyDevice_getDeviceInfo(SEXP handle, int *status)
>> {
>> groovyHandle *gh = R_ExternalPtrAddr(handle);
>> *status = GroovyStatus(gh);
>> }
>>
>> This all used to work fine. As of 2.15.0, I now get this:
>> Warning message:
>> In getDeviceInfo() :
>> passing an object of type 'externalptr' to .C (arg 1) is deprecated
>>
>> Passing the same handle to a .Call() does [of course] work fine.
>>
>> I thought my usage was exactly as designed. How then should I be
>> passing an externalptr to a .C() call?
>
> I think you shouldn't be doing that. You should be using .Call.
>
> If your code can handle external pointer objects (as in the example),
> this should be an easy transition. I haven't tested this, but I think
> the conversion to the .Call interface (less error checking) is simply
>
> SEXP_getDeviceInfo(SEXP handle, SEXP status)
> {
> groovyHandle *gh = R_ExternalPtrAddr(handle);
> INTEGER(Sstatus)[0] = GroovyStatus(gh);
> return R_NilValue;
> }
>
>
> If your code is using the pointer just as an opaque handle, I'd suggest
> keeping an array of them, and pass an index into that array: then .C
> will be fine.
>
> Duncan Murdoch



More information about the R-devel mailing list