我正在创建一个R包,我打算提交给CRAN,它有一个函数调用用C编写的例程。如何在R函数中以独立于平台的方式加载编译的C例程?我可以通过以下方式使我的软件包在基于英特尔的Mac上运行:
function(mydata)
{
dyn.load(file.path(.Library,"mypkg/libs/i386",paste("mypkg", .Platform$dynlib.ext, sep="")))
try(
output <- .C("myfunc_cversion",
in_data = as.double(mydata),
res_data = as.double(res),
PACKAGE = "mypkg")
)
result <- as.matrix(output$res_data)
return(result)
}
问题是调用dyn.load,我无法弄清楚如何以便携方式为我安装的软件包指定共享库的完整路径。
除了我应该使用的.Library还有R中的另一个变量,还是有比dyn.load更好的函数呢?
答案 0 :(得分:2)
我认为你太复杂了。您可以随时查询CRAN上现有的1800多个软件包。作为一般规则,大多数软件包在启动时通过.onLoad加载目标代码(甚至可以通过NAMESPACE文件自动化)---请参阅R扩展手册。
作为一个简单示例,您可以查看我的digest包,它使用文件R / zzz.R中的以下内容(这是手册中建议的标准方法)
.onLoad <- function(lib, pkg) {
library.dynam("digest", pkg, lib )
}
因此,在包加载后,动态库中的所有函数都可用于所有R函数以进行调用。这比为每个函数添加一个library.dynam()更通用(而且最重要的是你每个R会话只需要一次library.dynam())。
R本身处理扩展(.dll,.so,.dylib,...)和所有其他每个平台的细节。我认为没有理由偏离这种做法。所以请参阅手册,以及(字面上)数百个已发布的软件包。
答案 1 :(得分:2)
我发现如果我在包中使用名称空间,那么我也可以通过在包的NAMESPACE文件中使用useDynLib
指令来解决这个问题(如手册第1.6.3节所述)编写R扩展“版本2.9.1在www.r-project.org)。
我的NAMESPACE文件现在看起来像:
useDynLib(mypkg, myfunc_cversion)
export(myfunc)
然后我将R函数定义修改为:
myfunc <- function(mydata)
{
try(
output <- .C(myfunc_cversion,
in_data = as.double(mydata),
res_data = as.double(res) )
)
result <- as.matrix(output$res_data)
return(result)
}
也就是说,在PACKAGE
调用中,C函数名称周围没有引号,没有.C
参数。
答案 2 :(得分:0)
您需要查看library.dynam()
的手册页。它应该允许你做你想做的事,例如
function(mydata)
{
library.dynam("mysharedobject",package=c("mypkg"))
try(
output <- .C("myfunc_cversion",
in_data = as.double(mydata),
res_data = as.double(res),
PACKAGE = "mypkg")
)
result <- as.matrix(output$res_data)
return(result)
}
其中mysharedobject
是末尾没有.dll / .so等的共享对象文件的名称。
手册页还建议您仅在.onLoad()
或.First.lib()
函数中使用它。
HTH