From atp at piskorski.com  Mon Apr 21 22:13:16 2014
From: atp at piskorski.com (Andrew Piskorski)
Date: Mon, 21 Apr 2014 16:13:16 -0400
Subject: [Rd] read.table() code fails outside of the utils package
In-Reply-To: <535558E5.3030105@stats.ox.ac.uk>
References: <20140421155317.GA11783@piskorski.com>
	<27A253DD-2564-4F6E-AD37-24737BCF4FFE@r-project.org>
	<20140421170851.GA28440@piskorski.com>
	<535558E5.3030105@stats.ox.ac.uk>
Message-ID: <20140421201316.GA54548@piskorski.com>

On Mon, Apr 21, 2014 at 06:44:05PM +0100, Prof Brian Ripley wrote:
> On 21/04/2014 18:08, Andrew Piskorski wrote:

> >> .External(utils:::C_readtablehead, ...)
> >
> > Ah, that works fine, and is nice and simple.  So problem solved, thank
> > you!
> >
> > I do still wonder though, with the C symbol made visible in utils.so,
> 
> That isn't true on platforms which support hiding entry points.  Try
> 
> % nm -g library/utils/libs/utils.so | grep readtablehead
> 
> on Linux.

What isn't true?  That .External(utils:::C_readtablehead, ...)
should work for me under stock R 3.0.1?  My Linux (Ubuntu 12.04.3 LTS)
definitely does seem to support hiding entry points.

I have two separate installs, both built from source.  The first one
is stock, and the lower-case "t" here indicates that the readtablehead
symbol is local:

  andy at odo:~$ nm /usr/local/pkg/R-3.1-branch-20140416/lib/R/library/utils/libs/x86_64/utils.so | grep readtablehead
  00000000000059a0 t readtablehead

This second install is where I added "attribute_visible" to
readtablehead and recompiled, the upper-case "T" means it is a global
symbol:

  andy at odo:~$ nm /usr/local/pkg/R-3.1-branch-20140418/lib/R/library/utils/libs/x86_64/utils.so | grep readtablehead
  00000000000059c0 T readtablehead

Fortunately, calling .External(utils:::C_readtablehead, ...) works
with either of those installs.  But writing my won C code that calls
readtablehead only works in the second one where the symbol is global.

> > how come this still failed?:
> >
> >     .External("readtablehead", ..., PACKAGE="utils")
> >     Error: "readtablehead" not available for .External() for package "utils"
> 
> Rather, you need to tell us why that should have worked ....

That exact style of call DOES work for every cross-package use of .C
and .Call I've tried in my own code.  But I have never "registered"
any of my C code with R.  Obviously there is something different about
readtablehead and/or the utils package (probably the latter), and I am
trying to understand what it is.

> Maybe you failed to read in the code
> 
> R_init_utils(DllInfo *dll)
> {
>      R_registerRoutines(dll, NULL, CallEntries, NULL, ExtEntries);
>      R_useDynamicSymbols(dll, FALSE);
>      R_forceSymbols(dll, TRUE);
> }

I believe you are implying that using R_registerRoutines in a package
changes the behavior of .Call() and .External() such that ONLY
registered functions will be found, even if I invoke .External() with
a string function name like "readtablehead" rather than the registered
value C_readtablehead.  While if I do not register any C functions at
all in a package, then using a string name like "readtablehead" will
work as long as that C function symbol is visible.

> >     .External("readtablehead", ..., PACKAGE="utils")
> >     Error: "readtablehead" not available for .External() for package "utils"

> See 'Writing R Extensions'.

I already had, many times.  If this question is answered there, it was
not apparent to me.

-- 
Andrew Piskorski <atp at piskorski.com>



[Rd] read.table() code fails outside of the utils package
Andrew Piskorski