On Sat, Apr 19, 2014 at 2:29 AM, Simon Urbanek
<simon.urba...@r-project.org> wrote:
> Andrew,
>
> On Apr 18, 2014, at 9:55 AM, Andrew Piskorski <a...@piskorski.com> wrote:
>
>> In versions of R prior to 3.0, by default .C and .Call would find the
>> requested C function regardless of which shared library it was located
>> in.  You could use the PACKAGE argument to restrict the search to a
>> specific library, but doing so was not necessary for it to work.
>>
>> R 3.0 introduced a significant change to that behavior; from the NEWS
>> file:
>>
>>  CHANGES IN R 3.0.0:
>>  PERFORMANCE IMPROVEMENTS:
>>    * A foreign function call (.C() etc) in a package without a PACKAGE
>>      argument will only look in the first DLL specified in the
>>      NAMESPACE file of the package rather than searching all loaded
>>      DLLs.  A few packages needed PACKAGE arguments added.
>>
>> That is not merely a performance improvement, it is a significant
>> change in functionality.  Now, when R code in my package foo tries to
>> call C code located in bar.so, it fails with a "not resolved from
>> current namespace (foo)" error.  It works if I change all my uses of
>> .C and .Call to pass a PACKAGE="bar" argument.  Ok, I can make that
>> change in my code, no big deal.
>>
>> What surprises me though, is that there appears to be no way to invoke
>> the old (and very conventional Unix-style), "I don't want to specify
>> where the function is located, just keep searching until you find it"
>> behavior.  Is there really no way to do that, and if so, why not?
>>
>> Comparing the R sources on the 3.1 vs. 2.15 branches, it looks as if
>> this is due to some simple changes to resolveNativeRoutine in
>> "src/main/dotcode.c".  Specifically, the newer code adds this:
>>
>>   errorcall(call, "\"%s\" not resolved from current namespace (%s)",
>>             buf, ns);
>>
>> And removes these lines:
>>
>>   /* need to continue if the namespace search failed */
>>   *fun = R_FindSymbol(buf, dll.DLLname, symbol);
>>   if (*fun) return args;
>>
>> Is that extra call to R_FindSymbol really all that's necessary to
>> invoke the old "keep searching" behavior?  Would it be a good idea to
>> provide an optional way of finding a native routine regardless of
>> where it's located, perhaps via an optional PACKAGE=NA argument to .C,
>> .Call, etc.?
>>
>> And now I see that help(".Call") says:
>>
>>   'PACKAGE = ""' used to be accepted (but was undocumented): it is
>>    now an error.
>>
>> I assume passing PACKAGE="" used to invoke the same "keep searching"
>> behavior as not passing any PACKAGE argument at all.  So apparently
>> the removal of functionality was intentional.  I'd like to better
>> understand why.  Why should that be an error?  Or said another way,
>> why has traditional Unix-style symbol resolution been banned from use
>> with .C and .Call ?
>>
>
> I cannot speak for the author, but a very strong argument is to prevent 
> (symbol) namespace issues. If you cannot even say where the symbol comes 
> from, you have absolutely no way of knowing that the symbol you get has 
> anything to do with the symbol you intended to get, because you could get any 
> random symbol in any shared object that may or may not have anything to do 
> with your code. Note that even you as the author of the code have no control 
> over the namespace so although you intended this to work, loading some other 
> package can break your code - and in a fatal manner since this will typically 
> lead to a segfault. Do you have any strong use case for allowing this given 
> how dangerous it is? Ever since symbol registration has been made easy, it's 
> much more efficient and safe to use symbols directly instead.
>


As a follow-up to this, note that with traditional Unix symbol
resolution it was forbidden to have two different routines with the
same name linked into an object. That just isn't an option for R
because of the package system.  This isn't theoretical: the PACKAGE=
argument was introduced when finding the wrong symbol resolution
became a real problem late last century
(http://marc.info/?l=r-devel&m=107151103308418&w=2), but there wasn't
a good cross-package calling mechanism for quite a while. Now there is
a cross-package mechanism that works, where the Unix-style approach
cannot be made to work safely with packages from multiple authors.

   -thomas


-- 
Thomas Lumley
Professor of Biostatistics
University of Auckland

______________________________________________
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel

Reply via email to