英文:
golang os.Setenv does not work in cgo C.dlopen?
问题
由于某种原因,我无法将$LD_LIBRARY_PATH设置为全局环境变量。我尝试在golang代码中使用os.Setenv来设置它。
os.Setenv("LD_LIBRARY_PATH", my_library_paths)
lib := C.dlopen(C.CString(libpath), C.RTLD_LAZY)
我使用另一个C++函数来获取$LD_LIBRARY_PATH
,它显示正确。
但是lib返回<nil>
,而C.dlerror()显示:
libhasp_linux_x86_64_demo.so: cannot open shared object file: No such file or directory
这意味着$LD_LIBRARY_PATH在dlopen中不起作用,cgo找不到依赖库。
我不知道为什么。希望有人能帮助我。谢谢!
英文:
For some reason, I can not set $LD_LIBRARY_PATH to global env. I try to set it up in golang code use os.Setenv.
os.Setenv("LD_LIBRARY_PATH", my_library_paths)
lib := C.dlopen(C.CString(libpath), C.RTLD_LAZY)
I use another C++ function to get $LD_LIBRARY_PATH
, it shows corretly.
But lib returns '<nil>', and C.dlerror() shows
>> %!(EXTRA string=libhasp_linux_x86_64_demo.so: cannot open shared object file: No such file or directory)
Means $LD_LIBRARY_PATH does not work in dlopen, cgo can not find depend libraries.
I don't know why.Hope some one can help me.Thanks!
答案1
得分: 2
看起来你正在尝试从“同一进程内”调用os.Setenv("LD_LIBRARY_PATH", ...)
和C.dlopen()
。
根据dlopen(3)的手册:
否则,动态链接器按以下方式搜索对象
...
如果在程序启动时,环境变量LD_LIBRARY_PATH被定义为包含以冒号分隔的目录列表,则会搜索这些目录。
关键词是“在程序启动时”。我们可以在glibc源码elf/dl-load.c中的dlopen
实现中看到,它查看一个全局变量__rtld_env_path_list.dirs
,该变量在搜索要加载的库时已经被设置好了;它不会查看当前的$LD_LIBRARY_PATH
的值。
如果你想在C.dlopen
中使用LD_LIBRARY_PATH
来查找内容,那么你需要在进程启动之前设置它(例如通过运行LD_LIBRARY_PATH=/my/path go run my-app.go
)。
英文:
It looks like you're trying to call os.Setenv("LD_LIBRARY_PATH", ...)
and then C.dlopen()
from within the same process.
From the man page 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.
The key phrase being, at the time the program is started. We can see in the implementation for dlopen
in the glibc source elf/dl-load.c that it looks at a global variable __rtld_env_path_list.dirs
that has already been set when searching for libraries to load; it does not look at the current value of $LD_LIBRARY_PATH
.
If you want to use LD_LIBRARY_PATH
to find things in C.dlopen
, then you'll need to set it before your process starts (by running e.g. LD_LIBRARY_PATH=/my/path go run my-app.go
).
答案2
得分: 0
正如KJ Tsanaktsidis正确回答的那样,LD_LIBRARY_PATH
在进程启动后没有效果;您必须在启动进程之前设置它。
一种常见的技术是检查LD_LIBRARY_PATH
的当前值,如果不符合您的要求,将其设置为新值,并重新exec
进程。
话虽如此,不清楚您为什么要首先设置LD_LIBRARY_PATH
。如果您使用绝对路径调用dlopen
,它将愉快地打开不在LD_LIBRARY_PATH
上的库。也就是说,不要这样做:
> os.Setenv("LD_LIBRARY_PATH", my_library_paths)
<br>
> lib := C.dlopen(C.CString(libpath), C.RTLD_LAZY)
而是这样做:
lib := C.dlopen(C.CString(absolute_path_to_library), C.RTLD_LAZY)
英文:
As KJ Tsanaktsidis correctly answered, LD_LIBRARY_PATH
has no effect after the process has started; you must set it before starting the process.
A common technique is to examine current value of LD_LIBRARY_PATH
, and if it's not to your liking, set it to new value and re-exec
the process.
That said, it's not clear why you want set LD_LIBRARY_PATH
in the first place. dlopen
will happily open a library which is not on LD_LIBRARY_PATH
if you invoke dlopen
with absolute path. That is, instead of doing this:
> os.Setenv("LD_LIBRARY_PATH", my_library_paths)
<br>
> lib := C.dlopen(C.CString(libpath), C.RTLD_LAZY)
do this:
lib := C.dlopen(C.CString(absolute_path_to_library), C.RTLD_LAZY)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论