给定可执行文件中的地址,该dladdr
函数可用于向动态链接器查询包含该地址的动态链接图像;即,给定对插件中符号的引用,dladdr
可以为您提供有关插件的动态链接信息。
运行时查找可能如下所示:
// Sample: BundleClass.m, the principal class for the plugin
#import "BundleClass.h"
#import <dlfcn.h>
// We'll be using a reference to this variable compiled into the plugin,
// but we can just as easily use a function pointer or similar -- anything
// that will be statically compiled into the plugin.
int someVariable = 0;
@implementation BundleClass
+ (void)load {
Dl_info info;
if (dladdr(&someVariable, &info) != 0) {
NSLog(@"Plugin loaded from %s", info.dli_fname);
} else {
// Handle lookup failure.
}
}
@end
除了&someSymbol
,您还可以使用对函数的引用(例如&someFunctionDefinedInThePlugin
),但您应该注意不要传入可以动态分配的指针 - 因为这可能会失败,或者将您指向主机的内存空间过程。
在我的机器上,通过简单的 macOS 主机应用程序设置,以下加载代码:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
NSURL *bundleURL = [[NSBundle mainBundle] URLForResource:@"DynamicBundle" withExtension:@"bundle"];
if (!bundleURL) {
NSLog(@"Failed to find bundle!");
return;
}
NSLog(@"Bundle class before loading: %@", NSClassFromString(@"BundleClass"));
NSBundle *bundle = [NSBundle bundleWithURL:bundleURL];
NSError *error = nil;
if (![bundle loadAndReturnError:&error]) {
NSLog(@"Failed to load bundle: %@", error);
return;
}
NSLog(@"Bundle class after loading: %@", NSClassFromString(@"BundleClass"));
}
成功生产
Bundle class before loading: (null)
Loaded plugin from /Volumes/ExtSSD/Developer/Xcode/DerivedData/HostApp/Build/Products/Debug/HostApp.app/Contents/Resources/DynamicBundle.bundle/Contents/MacOS/DynamicBundle
Bundle class after loading: BundleClass
这确实是磁盘上插件的路径。