我有一个动态库的句柄(通过使用 dlopen()
)。不管为什么,我都无法访问提供给 dlopen()
的路径,但需要另一个函数的路径。因此,我需要能够使用其句柄获取库的路径。
我试过使用 dladdr()
,就像我在应用程序的其他部分中所做的那样,但是在 macOS/iOS 上,您无法使用它来查找库的路径库句柄 它仅适用于库中符号的句柄。我可以尝试向库中添加一个“定位器符号”,并以这种方式完成任务,但我不想这样做。
我还尝试了 dlinfo()
和 RTLD_DI_LINKMAP
,但这在 macOS/iOS 上显然不可用。
最佳答案
令我惊讶的是,有关这方面的信息如此之少。许多解决方案在 macOS/iOS 上不可用。还有一些只是关于获取当前可执行文件的路径,与句柄无关。
经过大量搜索,我终于找到了一些资源,说要使用 _dyld_image_count()
和 _dyld_get_image_name()
遍历所有加载的图像。我最初决定不这样做,因为它看起来不像是一种不合理的缓慢做事方式。
最终,我决定迭代所有加载的图像,因为这是我遇到的唯一实际解决方案。我在谷歌上搜索了示例,但找不到有关该主题的任何教程。但是,我确实遇到了实现该功能的开源 C++ 库(找到 here )。
我把它翻译成普通的 C,去掉了一些多余的东西(比如去掉句柄)。在测试过程中,我注意到我想要的库总是在列表的最后(我最好的猜测是它按照它们加载的顺序存储它们,并且由于我的不是系统库,它将是最后加载的)。这保证了缓慢的性能(引用计算机 - 对人类来说它仍然几乎是瞬时的)。因此,我做了一个巧妙的优化,从列表的结尾开始搜索,而不是开头。
这是我的解决方案的最终代码:
// NOT a thread safe way of doing things
NSString *pathFromHandle(void* handle)
{
// Since we know the image we want will always be near the end of the list, start there and go backwards
for (uint32_t i = (_dyld_image_count() - 1); i >= 0; i--)
{
const char* image_name = _dyld_get_image_name(i);
// Why dlopen doesn't effect _dyld stuff: if an image is already loaded, it returns the existing handle.
void* probe_handle = dlopen(image_name, RTLD_LAZY);
dlclose(probe_handle);
if (handle == probe_handle)
{
return [NSString stringWithUTF8String:image_name];
}
}
return NULL;
}
请务必注意,此解决方案不是线程安全的,因为 _dyld_image_count()
和 _dyld_get_image_name()
本质上不是线程安全的。这意味着任何其他线程都可以加载/卸载图像并对我们的搜索产生负面影响。
另外,resource我曾质疑为什么 dlopen
对 _dyld_image_count()
没有影响。这是因为如果图像已经加载,dlopen
不会加载图像的新实例,而是返回它的现有句柄。
关于ios - 如何从其句柄(macOS/iOS)获取库的路径?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54201384/