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

  • 相关阅读:
    [InnoSetup]Inno Setup软件打包脚本
    inno setup 执行SQL
    用inno Setup制作web项目安装包
    Inno Setup执行SQL脚本的方法
    delphi的tserversocket控件如何接收16进制数
    Delphi 通信报Asynchronous socket error 10053错误的一个解决方法
    么正矩阵(酉矩阵)
    对称矩阵、Hermite矩阵、正交矩阵、酉矩阵、奇异矩阵、正规矩阵、幂等矩阵
    RSVP协议的基本概念介绍
    计算机顶级会议的历年最佳文章
  • 原文地址:https://www.cnblogs.com/javastart/p/15002329.html
Copyright © 2011-2022 走看看