zoukankan      html  css  js  c++  java
  • 第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 ",

                  __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 ",

                  __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

  • 相关阅读:
    kafka学习总结010 --- 实际项目中遇到的问题1
    kafka学习总结009 --- HW和LEO
    spring学习总结001 --- IOC控制反转、DI依赖注入
    kafka学习总结008 --- 生产者生产数据流程(参照源码)
    kafka学习总结007 --- 生产者Java API实例
    kafka学习总结006 --- 生产者事务
    kafka学习总结005 --- at-exactly-once语义
    kafka学习总结004 --- 生产者ISR
    kafka学习总结003 --- 生产者分区策略
    计算机基础-1(进制转换)
  • 原文地址:https://www.cnblogs.com/javastart/p/15002329.html
Copyright © 2011-2022 走看看