我已经构建了一个软件包,用于与R的HDFQL进行交互。它依赖于HDFQL 2.1.0提供的R包装器和DLL/SOS。这些软件包使用DLL在Windows中完美工作,但是由于某种原因,HDFQL库SOS无法在Linux环境中加载。我在Travis和本地Docker Linux/R容器上都尝试过。
函数hql_load()
中包含的相关代码如下。假设将HDFQL提取到当前目录中的文件夹"/hdfql-2.1.0",这意味着
dllpath = c("/hdfql-2.1.0/lib/libHDFql.so", "/hdfql-2.1.0/wrapper/R/libHDFqlR.so")
我使用normalizePath(dllpath, mustWork = TRUE)
检查了这些路径是否存在,还检查对象是否成功加载并出现在getLoadedDlls()
。
# ... starting at line 153 of connect.r ... #
wrapper.file = tempfile(fileext = ".r")
wrapper.lines = readLines(wrapperpath)
writeLines(wrapper.lines[-grep("dyn\.load", wrapper.lines)],
wrapper.file)
# load DLLs
for (dll in dllpath) {
dyn.load(dll, local = FALSE, now = TRUE)
if (!dll %in% sapply(getLoadedDLLs(), function(x) normalizePath(x[["path"]], mustWork = FALSE))) {
stop("Error loading HDFql shared library object ", dll)
}
}
# load wrapper
wrapper = new.env(parent = .BaseNamespaceEnv)
tryCatch(
sys.source(wrapper.file, envir = wrapper, toplevel.env = packageName()),
error = function(e) {
stop("Failed to execute HDFql R wrapper.n Additional Information:n",
e)
}
)
assign("wrapper", wrapper, envir = hql)
invisible(NULL)
}
错误发生在sys.source
呼叫中,以评估HDFQL提供的包装文件中的代码,而>在初始化调用中均具有。包装器内容在下面;请注意,在上面的功能中,我在对包装器进行评估之前删除了包装器的dyn.load
调用(事先加载了库(。
hdfql_operating_system = Sys.info()["sysname"]
if (hdfql_operating_system == "Windows")
{
dyn.load("HDFqlR.dll")
hdfql_shared_library <- "HDFqlR"
} else if (hdfql_operating_system == "Linux")
{
dyn.load("libHDFqlR.so")
hdfql_shared_library <- "libHDFqlR"
} else # macOS
{
dyn.load("libHDFqlR.dylib")
hdfql_shared_library <- "libHDFqlR.dylib"
}
rm(hdfql_operating_system)
#===========================================================
# INITIALIZE HDFQL R WRAPPER SHARED LIBRARY
#===========================================================
hdfql_initialize_status = .Call("_hdfql_initialize", PACKAGE = hdfql_shared_library)
错误:无法执行HDFQL R包装器。
其他信息:
eval中的错误(parse(wrapper.file(,envir = wrapper(:找不到/加载hdfql共享库'libhdfql.o'!
我已经对数周进行故障排除,几乎没有进展。谁能告诉我为什么库在Linux系统中未正确加载?
@ralfstubner的建议是正确的:问题是在Linux计算机上设置LD_LIBRARY_PATH
,以包括HDFQL库。有趣的是,我仍然必须为dyn.load
调用中的DLL提供完整的合格路径名称,并且无法使用Sys.setenv
或DLLpath
参数到dyn.load
来临时修改LD_LIBRARY_PATH
----相反,我已经在travis.yaml
/Dockerfile
上添加了一条线更新LD_LIBRARY_PATH
:
export LD_LIBRARY_PATH=${HDFQL_DIR}/lib:${HDFQL_DIR}/wrapper/R:$LD_LIBRARY_PATH
我仍然不明白为什么我无法使用例如。
解决问题Sys.setenv(LD_LIBRARY_PATH = paste(dirname(dll), Sys.getenv("LD_LIBRARY_PATH"), sep = ":")
或
dyn.load(basename(dll), DLLpath = dirname(dll))
由于这两个命令(理论上(应该修改搜索路径以包括HDFQL目录。我很感谢可以解释这一点的任何答案。
我也很惊讶地发现,一旦我更新了LD_LIBRARY_PATH
,我就被Windows Build在Windows Build上从未出现的环境绑定和名称空间问题击中 - 但这是一个单独的问题。