golang os.Setenv 在 cgo C.dlopen 中不起作用?

golang os.Setenv does not work in cgo C.dlopen?

出于某种原因,我无法将 $LD_LIBRARY_PATH 设置为全局环境。我尝试使用 os.Setenv.

在 golang 代码中设置它
os.Setenv("LD_LIBRARY_PATH", my_library_paths)

lib := C.dlopen(C.CString(libpath), C.RTLD_LAZY)

我用另一个C++函数得到$LD_LIBRARY_PATH,它显示正确。 但是 lib returns '' 和 C.dlerror() 显示

>> %!(EXTRA string=libhasp_linux_x86_64_demo.so: cannot open shared object file: No such file or directory)

表示$LD_LIBRARY_PATH在dlopen中不工作,cgo找不到依赖库。

我不知道 why.Hope 有人可以帮忙 me.Thanks!

您似乎正试图在同一进程中从 调用 os.Setenv("LD_LIBRARY_PATH", ...) 然后 C.dlopen()

来自手册页 dlopen(3)

Otherwise, the dynamic linker searches for the object as follows

...

If, at the time that the program was started, the environment variable LD_LIBRARY_PATH was defined to contain a colon-separated list of directories, then these are searched.

关键字是,程序启动时。我们可以在 glibc source elf/dl-load.c 中的 dlopen 的实现中看到它查看一个全局变量 __rtld_env_path_list.dirs ,该变量在搜索要加载的库时已经设置;它查看$LD_LIBRARY_PATH的当前值。

如果您想使用 LD_LIBRARY_PATHC.dlopen 中查找内容,那么您需要在进程开始之前设置它(通过 运行 例如 LD_LIBRARY_PATH=/my/path go run my-app.go ).

正如 KJ Tsanaktsidis 正确回答的那样,LD_LIBRARY_PATH 在进程启动后没有任何效果;您必须在 开始该过程之前 设置它。

一种常用的技术是检查 LD_LIBRARY_PATH 的当前值,如果不合您的喜好,将其设置为新值 重新 exec 过程。

就是说,不清楚您为什么 想要 首先设置 LD_LIBRARY_PATH。如果您使用绝对路径调用 dlopendlopen 将愉快地打开一个不在 LD_LIBRARY_PATH 上的库。也就是说,而不是这样做:

os.Setenv("LD_LIBRARY_PATH", my_library_paths)
lib := C.dlopen(C.CString(libpath), C.RTLD_LAZY)

这样做:

  lib := C.dlopen(C.CString(absolute_path_to_library), C.RTLD_LAZY)