I am storing shared objects in a hierarchical folder structure. Shared libraries can depend on one another. At runtime, shared library X may need to load shared library Y. I am unsure what mechanism I can use to have library X locate Y.
我将共享对象存储在分层文件夹结构中。共享库可以相互依赖。在运行时,共享库X可能需要加载共享库Y.我不确定我可以使用什么机制让库X找到Y.
I'd rather not use -rpath because it doesn't translate well across platforms:
我宁愿不使用-rpath,因为它不能跨平台很好地翻译:
- How to set the runtime path (-rpath) of an executable with gcc under Mac OSX?
- Is there a Windows/MSVC equivalent to the -rpath linker flag?
如何在Mac OSX下使用gcc设置可执行文件的运行时路径(-rpath)?
是否有与-rpath链接器标志等效的Windows / MSVC?
I can't put the shared objects in a single directory because of potential name *es. LD_LIBRARY_PATH and PATH are not usable since I'd be adding a lot of paths.
由于潜在的名称冲突,我无法将共享对象放在单个目录中。 LD_LIBRARY_PATH和PATH不可用,因为我要添加很多路径。
This has me wondering whether I can modify the LD_LIBRARY_PATH in the constructor of a shared object (using -Wl,-init). This would require the constructor to be run before the runtime linking happens. I couldn't find whether this is the case.
这让我想知道是否可以在共享对象的构造函数中修改LD_LIBRARY_PATH(使用-Wl,-init)。这将需要在运行时链接发生之前运行构造函数。我无法找到是否是这种情况。
In essence, I'm thinking about doing the following (haven't tried this code out yet):
本质上,我正在考虑做以下事情(还没有尝试过这个代码):
Add this function to the library source code:
将此函数添加到库源代码:
extern char *searchPath;
void construct() {
char *libPath = getenv("LD_LIBRARY_PATH");
char *new_libPath = malloc(1 + snprintf(NULL, 0, "%s:%s", libPath, searchPath);
sprintf(new_libPath, "%s:%s", libPath, searchPath);
setenv("LD_LIBRARY_PATH", new_libPath, 0);
}
And compile with:
并编译:
gcc foo.c --shared -o foo -Wl,-init,construct
1 个解决方案
#1
No, you cannot in general. Some linkers might support it, but others definitely won't. Many dynamic linkers will just ignore changes to LD_LIBRARY_PATH
or equivalent after the main executable is loaded, so you may not even be able to influence the loading path at all at runtime. Other linkers may not even try to call initializers or constructors before all the libraries are linked (the Mac OS X dyld
appears to behave this way, for example).
不,你不能一般。一些链接器可能会支持它,但其他人肯定不会支持它。在加载主可执行文件之后,许多动态链接器将忽略对LD_LIBRARY_PATH或等效的更改,因此您甚至可能无法在运行时完全影响加载路径。在链接所有库之前,其他链接器甚至可能不会尝试调用初始化器或构造器(例如,Mac OS X dyld似乎以这种方式运行)。
Furthermore, some linkers won't even load two libraries that have the same soname
, as they would be considered the same library. So, considering that you have potential name *es in your libraries, this would preclude even loading them automatically in the first place.
此外,一些链接器甚至不会加载具有相同soname的两个库,因为它们将被视为相同的库。因此,考虑到您的库中存在潜在的名称冲突,这将排除在第一时间自动加载它们。
For runtime loading of libraries, POSIX provides dlopen
and dlsym
. dlopen
lets you load an arbitrary library by file path, and dlsym
lets you grab pointers to symbols defined within that library Consider using those instead of some dynamic path-changing hack - dlopen
and dlsym
are portable and reasonably easy to use. Yes, you don't get "automatic" symbol resolution (in that you have to dlsym
everything yourself), but there are ways to design your libraries to make this easier (or use macros to make resolution easier).
对于库的运行时加载,POSIX提供了dlopen和dlsym。 dlopen允许你通过文件路径加载任意库,dlsym允许你抓取指向该库中定义的符号的指针考虑使用那些而不是一些动态路径改变hack - dlopen和dlsym是可移植的并且相当容易使用。是的,您没有获得“自动”符号解析(因为您必须自己编写所有内容),但有一些方法可以设计您的库以使其更容易(或使用宏来简化分辨率)。
On Windows, you can use LoadLibrary
and GetProcAddress
similarly. If you want a nice cross-platform library that smooths over the platform differences, consider something like libltdl.
在Windows上,您可以类似地使用LoadLibrary和GetProcAddress。如果你想要一个很好的跨平台库来平滑平台差异,可以考虑像libltdl这样的东西。
#1
No, you cannot in general. Some linkers might support it, but others definitely won't. Many dynamic linkers will just ignore changes to LD_LIBRARY_PATH
or equivalent after the main executable is loaded, so you may not even be able to influence the loading path at all at runtime. Other linkers may not even try to call initializers or constructors before all the libraries are linked (the Mac OS X dyld
appears to behave this way, for example).
不,你不能一般。一些链接器可能会支持它,但其他人肯定不会支持它。在加载主可执行文件之后,许多动态链接器将忽略对LD_LIBRARY_PATH或等效的更改,因此您甚至可能无法在运行时完全影响加载路径。在链接所有库之前,其他链接器甚至可能不会尝试调用初始化器或构造器(例如,Mac OS X dyld似乎以这种方式运行)。
Furthermore, some linkers won't even load two libraries that have the same soname
, as they would be considered the same library. So, considering that you have potential name *es in your libraries, this would preclude even loading them automatically in the first place.
此外,一些链接器甚至不会加载具有相同soname的两个库,因为它们将被视为相同的库。因此,考虑到您的库中存在潜在的名称冲突,这将排除在第一时间自动加载它们。
For runtime loading of libraries, POSIX provides dlopen
and dlsym
. dlopen
lets you load an arbitrary library by file path, and dlsym
lets you grab pointers to symbols defined within that library Consider using those instead of some dynamic path-changing hack - dlopen
and dlsym
are portable and reasonably easy to use. Yes, you don't get "automatic" symbol resolution (in that you have to dlsym
everything yourself), but there are ways to design your libraries to make this easier (or use macros to make resolution easier).
对于库的运行时加载,POSIX提供了dlopen和dlsym。 dlopen允许你通过文件路径加载任意库,dlsym允许你抓取指向该库中定义的符号的指针考虑使用那些而不是一些动态路径改变hack - dlopen和dlsym是可移植的并且相当容易使用。是的,您没有获得“自动”符号解析(因为您必须自己编写所有内容),但有一些方法可以设计您的库以使其更容易(或使用宏来简化分辨率)。
On Windows, you can use LoadLibrary
and GetProcAddress
similarly. If you want a nice cross-platform library that smooths over the platform differences, consider something like libltdl.
在Windows上,您可以类似地使用LoadLibrary和GetProcAddress。如果你想要一个很好的跨平台库来平滑平台差异,可以考虑像libltdl这样的东西。