第1年7月12日 iOS运行加载动态库
1.
在运行时加载动态库,是指不需要在工程中引入动态库,作为替代,在代码中使用dlopen()这个函数来加载动态库,在调用完成之后,需要调用相同次数的dlclose()函数来关闭动态库。
除了dlopen()和dlclose()以外,另外还有一个dlsym()函数来根据传入的symbol获取对应数据或函数的地址。在本例中,会使用runtime机制来代替dlsym()函数。(dlsym()一般是在c或c++中使用)
1.创建新工程DylibDemo-Runtime,添加被调用库的头文件LibPerson.h(这里不需要添加LibPersonFramework.framework)
2.在main.h文件中加载和调用LibPersonFramework.framework
void loadWhenRunTime(){
// Open the library.
NSString *bundlePath = [[NSBundle mainBundle]pathForResource:@"LibPersonFramework" ofType:nil];
void* lib_handle = dlopen([bundlePath UTF8String], RTLD_LOCAL);
if (!lib_handle) {
NSLog(@"[%s] main: Unable to open library: %s\n",
__FILE__, dlerror());
exit(EXIT_FAILURE);
}
Class class_person = objc_getClass("LibPerson");
LibPerson *person = [class_person new];
person.name = @"wang";
[person watch];
[person eat];
// Close the library.
if (dlclose(lib_handle) != 0) {
NSLog(@"[%s] Unable to close library: %s\n",
__FILE__, dlerror());
exit(EXIT_FAILURE);
}
}
dlopen()函数需要传入两个参数path和mode,path表示动态库的mach-o文件的路径,mode中可以包含多个标识符,比如RTLD_LAZY和RTLD_NOW表示动态库中的symbol什么时候被加载,RTLD_GLOBAL和RTLD_LOCAL表示symbol的可见性。(详情可通过终端命令man dlopen查看)
上述代码中,path指定动态库是在生成的app包中,文件名为LibPersonFramework;mode的值是RTLD_LOCAL,表示在使用dlsym()函数时,只能通过dlopen()函数返回的handle来获取传入的symbol的地址,由于在例中并不会使用dlsym()函数,所以大可不必关注这个值。
另外,在上述代码中还有一点需要注意的,在创建LibPerson类的对象时,不能直接使用LibPerson *person = [LibPerson new],如果这样做,程序会报如下编译错误:
Undefined symbols for architecture arm64:
"_OBJC_CLASS_$_LibPerson", referenced from:
objc-class-ref in main.o
ld: symbol(s) not found for architecture arm64
这是因为在编译时,如果调用了[LibPerson new],编译器会去验证app的mach-o文件以及它依赖的动态库的mach-o文件中是否有这个类的定义。
由于在编译时,程序还没有加载动态库LibPersonFramework,而程序只包含了LIbPerson类的头文件,并没有它对应的.m文件(编译器只会将.m文件编译到最终的mach-o文件中),所以编译器在app的mach-o文件以及它依赖的动态库中找不到LibPerson类的定义,然后编译器就报错了。
从上述代码可以看出,在创建LibPerson类的对象时,程序中其实已经加载了LibPersonFramework,也就是说,在那个时候程序中已经有这个类的定义了。所以,上述代码中使用了下列代码来”欺骗“编译器。
Class class_person = objc_getClass("LibPerson");
LibPerson *person = [class_person new];
https://www.jianshu.com/p/be0c6fe4fba0?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation