【问题标题】:How does the PACKAGE argument to .Call work?.Call 的 PACKAGE 参数如何工作?
【发布时间】:2016-11-21 05:46:49
【问题描述】:

.Call 似乎记录得很差; ?.Call 解释了 PACKAGE 参数:

PACKAGE:如果提供,则将搜索字符串 .NAME 限制在此参数给出的 DLL 中(加上常规扩展名,'.so','.dll',...)。

这个参数跟在...之后,所以它的名字不能缩写。

这是为了增加包的安全性,通过使用这个参数可以确保没有其他包可以覆盖它们的外部符号,也可以加快搜索速度(见“注意”)。

并在注释中:

如果要经常使用这些函数之一,请指定 PACKAGE(将搜索限制在单个 DLL)或将 .NAME 作为本机符号对象之一传递。搜索符号可能需要很长时间,尤其是在加载了许多命名空间时。

对于链接到 R 的符号,您可能会看到 PACKAGE = "base"。请勿在您自己的代码中使用此符号:此类符号不是 API 的一部分,可能会在没有警告的情况下更改。

PACKAGE = "" 曾经被接受(但未被记录):现在是一个错误。

但没有使用示例。

尚不清楚PACKAGE 参数的工作原理。例如,在回答this 问题时,我认为以下应该有效,但它没有:

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

相反,这是可行的:

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

这仅仅是因为C_BinCount 未导出吗?也就是说,如果hist.default的内部代码添加了PACKAGE = "graphics",这会起作用吗?

这看起来很简单,但真的很难找到这个论点的用法;我发现的所有消息来源都只是顺便提及(12345)......这个实际工作的例子将不胜感激(即使它只是引用代码在现有包中找到)

(出于自包含目的,如果您不想从其他问题复制粘贴代码,这里是xbreaks):

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

【问题讨论】:

  • 好问题,我刚刚google了一下,我发现了一些可以给你一些提示的东西,以防万一没有人有经验biostat.jhsph.edu/~bcaffo/statcomp/files/dotCall.pdf
  • @Learner 确实是我的问题中的链接 3
  • 使用 .Call 来自其他包的未记录的东西是一个非常糟糕的主意,并且是应该保持未记录的未记录事物的完美示例。这意味着它不应该记录在 SO 文档站点上。或其他任何地方。
  • @MichaelChirico 当然,但这仍然不能消除您在这个问题上......错的基本事实。

标签: r internals


【解决方案1】:

C_BinCount 是类“NativeSymbolInfo”的对象,而不是命名 C 级函数的字符串,因此 PACKAGE(“限制搜索字符串 .NAME”)不相关。 C_BinCount 通过在图形包 NAMESPACE 中的 useDynLib() 中提及而成为符号。

作为 R 符号,C_BinCount 的解析与其他符号遵循相同的规则——它不是从 NAMESPACE 导出的,因此只能通过 graphics:::C_BinCount 访问。而且,出于这个原因,健壮的代码开发是禁区。由于 C 入口点是作为符号导入的,它可作为字符串使用,因此.Call("C_BinCount", ...) 将不起作用。

使用 NativeSymbolInfo 对象告诉 R C 代码所在的位置,因此无需通过 PACKAGE 再次这样做;使用符号而不是字符串的选择是由包开发人员做出的,我认为通常被认为是好的做法。在 NativeSymbolInfo 发明之前开发的许多包都使用 PACKAGE 参数,如果我 grep Bioconductor 源代码树,则有 4379 行带有 .Call.*PACKAGE,例如,here

其他信息(包括示例)位于编写 R 扩展部分 1.5.4

【讨论】:

  • 谈论深奥的文档...我尝试了.Call("C_BinCount", x, breaks, TRUE, TRUE, PACKAGE = "graphics")并得到了一个不同的错误("C_BinCount"不适用于.Call()对于包"graphics")...这是因为它没有导出?有没有办法在这里使用PACKAGE参数来执行调用?
  • 另外,您知道任何使用PACKAGE 参数的实际 R 代码吗?找到一个“在野外”的例子会很有用
  • 我已经更新了我的答案——包作者选择不通过字符串公开符号,所以再多的输入都不会使“C_BinCount”工作。野外有很多例子;我链接到一个。
  • @MichaelChirico 它在 NAMESPACE 文件 useDynLib() 中创建了一个符号;我已经更新了我的答案。
  • @MichaelChirico RE:实际示例,如果您使用 Rcpp(属性)创建包,生成的包装函数将使用 .CallPACKAGE 参数。这是minimal example
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多