首页 > 解决方案 > 在 R Linux 上使用 dyn.load 加载共享库时出现问题,但等效的 Windows 构建工作正常

问题描述

我已经构建了一个用于与 R 中的 HDFql 交互的。它依赖于 HDFql 2.1.0 提供的 R 包装器和 DLL/SO。这些包使用 DLL 在 Windows 中完美运行,但由于某种原因,HDFql 库 SO 无法在 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.sourceHDFql 提供的包装文件中的代码进行评估的调用中,特别是在初始化调用中。包装内容如下;请注意,在我上面的函数中,我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 中的错误(解析(wrapper.file),envir = wrapper):找不到/加载 HDFql 共享库“libHDFql.so”!

我已经对此进行了数周的故障排除,但进展甚微。谁能告诉我为什么库在 Linux 系统中没有正确加载?

标签: rshared-librarieshdfql

解决方案


@RalfStubner 的建议是正确的:问题是LD_LIBRARY_PATH在 Linux 机器上设置包含 HDFql 库。有趣的是,我仍然必须在dyn.load调用中为 DLL 提供完整的限定路径名,并且无法使用Sys.setenv或临时修改的DLLpath参数--- 相反,我在/中添加了一行来更新:dyn.loadLD_LIBRARY_PATHtravis.yamlDockerfileLD_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 构建中从未出现过的环境绑定和命名空间问题——但这是一个单独的问题。


推荐阅读