How does the PACKAGE argument work for .Call?

.Call seems rather poorly documented; ?.Call gives an explanation of the PACKAGE argument:

PACKAGE : if specified, restrict the search for the .NAME character string to the DLL specified by this argument (plus the regular extension, .so, .dll, ...).

This argument follows ... so its name cannot be shortened.

This is intended to add security for packages, which allows using this argument to ensure that no other package can override external characters, as well as speed up the search (see "Note").

And in the note:

If one of these functions will be used frequently, specify PACKAGE (to limit the search to one DLL) or pass .NAME as one of the symbol's native objects. Searching for characters can take a long time, especially if many namespaces are loaded.

You can see PACKAGE = "base" for characters associated with R. Do not use this in your own code: such characters are not part of the API and are subject to change without notice.

PACKAGE = "" was accepted (but was undocumented): now this is a mistake.

But there are no examples of use.

It is unclear how the PACKAGE argument works. For example, in answering this question, I thought the following should work, but it is not:

 .Call(C_BinCount, x, breaks, TRUE, TRUE, PACKAGE = "graphics") 

Instead it works:

 .Call(graphics:::C_BinCount, x, breaks, TRUE, TRUE) 

Is it just because C_BinCount not supported? I. If the internal hist.default code added PACKAGE = "graphics" , would it work?

It seems simple, but it is very rare to find use of this argument; none of the sources that I found mentions anymore ( 1 , 2 , 3 , 4 , 5 ) ... Examples of this actually working will be appreciated (even if it just refers to the code found in the existing package)

(for self-limiting purposes, if you do not want to copy-paste the code from another question, here are x and breaks ):

 x = runif(100000000, 2.5, 2.6) nB <- 99 delt <- 3/nB fuzz <- 1e-7 * c(-delt, rep.int(delt, nB)) breaks <- seq(0, 3, by = delt) + fuzz 
+8
r internals
source share
1 answer

C_BinCount is an object of the "NativeSymbolInfo" class, not a character string that names a C-level function, so PACKAGE (which restricts the search for a character string .NAME ") does not matter. C_BinCount is made a character by its mention in useDynLib() in the NAMESPACE graphic package.

As an R character, the C_BinCount permission obeys the same rules as other characters - it is not exported from NAMESPACE, therefore it is only accessible through graphics:::C_BinCount . And also, for this reason, offline for reliable code development. Since the entry point C is imported as a character, it is not available as a character string, so .Call("C_BinCount", ...) will not work.

Using the NativeSymbolInfo object tells R where the C code is located, so there is no need to do it again through PACKAGE; the choice of using a character rather than a character string was made by the package developer, and I think that in general this is considered good practice. Many packages developed before the invention of NativeSymbolInfo use the PACKAGE argument; if I use the Bioconductor source tree, there are 4,379 lines with .Call. * PACKAGE, for example here .

For more information, including examples, see "Writing R-Extensions" 1.5.4 .

+10
source share

All Articles