分类目录归档:项目实战

静态库、动态库的制作

1、命名规则

  • 静态库:lib+名称.a  —> libSian.a
  • 动态库:lib+名称.so —> libSian.so

2、静态库制作

  • 准备目录:include、lib、src
  • 头文件存放在include中,源文件存放在src中,库文件存放lib中
  • 生成.o文件:在src目录中gcc -c *.c -I ../include 
  • 生成.a文件:ar rcs lib/libCalc.a src/*.o // 将src下的所有.o文件在lib目录下生成.a文件
  • 利用静态库编译源文件:
    • gcc main.c lib/libCalc.a -o main.out -I include
    • gcc main.c -L lib -l Calc -I include // L库目录,l库名称(不带lib前缀)
  • 整体目录结构及生成文件
    • ── include
    • │   └── head.h
    • ├── lib
    • │   └── libCalc.a
    • ├── main.c
    • ├── main.out
    • └── src
    •     ├── sub.c
    •     ├── sub.o
    •     ├── sum.c
    •     └── sum.o
  • nm命令:nm lib/libCalc.a 可查看.a文件的内容,nm main.out同样可以查看

3、静态库的优缺点

  • 优点:
    • 编译时会根据需要以.o为单位包含库中的内容
    • 发布程序时,不需要提供相对应的库(因为已经打包到应用程序中)
    • 加载库时速度快
  • 缺点:
    • 程序体积变大;
    • 库发生变化需要重新编译

4、动态库制作

  • 生成与位置无关的.o文件
    • gcc -fPIC -c *.c -I ../include 
  • 生成动态库.so文件
    • gcc -shared src/*.o -o lib/libCalc.so -I include
  • 使用动态库编译源文件
    • gcc main.c lib/libCalc.so -o main.out -I include // 方式一
    • gcc main.c -L lib -l Calc -o main1.out -I include // 方式二
    • 两种方式都能生成可执行文件,但方式二生成的执行文件在执行时会报错,./main.out: error while loading shared libraries: libCalc.so: cannot open shared object file: No such file or directory
    • 解决动态库无法找到的问题:
      • 使用lld命令查看可执行文件:ldd main1.out
      • 出现该问题的原因是无法通过环境变量找到动态库文件
      • 方法一:将libCalc.so拷贝到/lib下即可解决;(不推荐)
      • 方法二:export LD_LIBRARY_PATH=./lib 临时导入可以解决,当前终端生效;(临时)
      • 方法三:如果需要每次打开时都有效,在~.bashrc文件的末尾行添加上述指令;(重启终端)
      • 方法四:修改/etc/ld.so.conf文件,加入lib的绝对路径,sudo ldconfig -v更新 (建议)

5、动态库优缺点

  • 优点:
    • 动态库更新不需要更新源程序(接口不变情况下)
    • 执行程序体积小,不需要打包到应用程序中
  • 缺点:
    • 发布程序时需要提供给用户
    • 没有打包到应用程序中,执行效率相对慢一点

关于Cocoapods速度慢的问题,更换国内镜像源

CocoaPods 是一个 Cocoa 和 Cocoa Touch 框架的依赖管理器,具体原理和 Homebrew 有点类似,都是从 GitHub 下载索引,然后根据索引下载依赖的源代码。

对于旧版的 CocoaPods 可以使用如下方法使用 tuna 的镜像:

$ pod repo remove master
$ pod repo add master https://mirrors.tuna.tsinghua.edu.cn/git/CocoaPods/Specs.git
$ pod repo update

新版的 CocoaPods 不允许用pod repo add直接添加master库了,但是依然可以:

$ cd ~/.cocoapods/repos 
$ pod repo remove master
$ git clone https://mirrors.tuna.tsinghua.edu.cn/git/CocoaPods/Specs.git master

最后进入自己的工程,在自己工程的podFile第一行加上:

source 'https://mirrors.tuna.tsinghua.edu.cn/git/CocoaPods/Specs.git'

来自清华的链接:https://mirrors.tuna.tsinghua.edu.cn/help/CocoaPods/

通过对象地址获取对象的虚函数列表

1、C++中多态是一种泛型编程思想,虚函数是实现这个思想的语法基础;

2、虚函数列表简称虚表,出现在对象的头部,即虚表的首地址即对象地址;

3、通过创建好的对象,可以得到虚表,从而通过偏移可获取所有虚函数的地址;

4、示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>
using namespace std;
// Person类定义
class Person{
public:
    virtual void MethodOne(){   // 虚函数
        cout << __func__ << endl;
    }
    virtual void MethodTwo(){   // 虚函数
        cout << __func__ << endl;
    }
};
// Student类定义
class Student: public Person{
 
};
// 定义一个指向函数的指针类型
typedef void (*method)();
int main(int argc, const char *argv[]){
    Person *p = new Student();
    // 1、对象地址即虚表地址(对象的头部即虚表)
    // 2、取变量p的值得到虚表地址(强转为指向函数指针的数组)
    method *method_map = (method *)*(method*)p;
    // 虚函数数组中取值,单个对象为函数体地址
    method method1 = *method_map[0];
    method method2 = *method_map[1];
    method1();
    method2();
    return 0;
}

5、执行结果:

MethodOne
MethodTwo
Program ended with exit code: 0