第一章 C语言 —— 静态库和动态库

很多时候需要把一组代码编译成一个库,这个库在很多项目中都要用到。

 

 

 

1)程序文件 (虽然实际上没太大必要)

 

文件目录结构

[www@zhoubc test]$ tree
|-- main.c
|-- stack
|   |-- is_empty.c
|   |-- pop.c
|   |-- push.c
|   |-- stack.c
|   |-- stack.h

 代码所示

 

/* @package: stack/stack.c */
char stack[512];
int top = -1; 
 
/* @package:stack/push.c */
extern char stack[512];
extern int top;

void push(char c){ 
    stack[++top] = c;
}

 

/* @package:stack/pop.c */
extern char stack[512];
extern int top;

char pop(void){
    return stack[top--];
}

 

/* @package:stack/is_empty.c */

extern int top;
int is_empty(){
    return top == -1; 
}
 
/* @package:stack/stack.h */

#ifndef STACK_H
#define STACK_H
extern void push(char c); 
extern char pop(void);
extern int is_empty();
#endif

 

主函数:

/* @package:main.c */
#include <stdio.h>

#include "stack.h"

int main(){
    extern char stack[512];
    push('a');
    printf("%d \n",stack[0]);
    return 0;
}
 

 

2) stack.cpush.cpop.cis_empty.c 编译成目标文件

[www@zhoubc test]$ gcc -c stack/*.c

[www@zhoubc test]$ ls
is_empty.o  main.c  pop.o  push.o  stack  stack.o

 

 3)打包成一个静态库libstack.a

[www@zhoubc test]$ ar rs libstack.a *.o
ar: creating libstack.a

 或

[www@zhoubc test]$ ar r libstack.a *.o
[www@zhoubc test]$ranlib libstack.a

 解析:

        库文件名都是以lib 开头的,静态库以.a 作为后缀,表示Archive

        ar :把目标文件打包成静态库.

             选项r: 表示将后面的文件列表添加到文件包,如果文件包不存在就创建它,如果文件包中已有同名文件就替换成新的

             选项s :专用于生成静态库的,表示为静态库创建索引,这个索引被链接器使用.ranlib 命令也可以为静态库创建索引

 

4)编译链接在一起

[www@zhoubc test]$ gcc main.c -L. -lstack -Istack -o main

 

-L 选项告诉编译器去哪里找需要的库文件,-L. 表示在当前目录找(注意,即使库文件就在当前目录,编译器默认也不会去找的,所以-L. 选项不能少)

-lstack 告诉编译器要链接libstack

-I 选项告诉编译器去哪里找头文件

 

5)运行

[www@zhoubc test]$ ./main 
97 

 

=================================================================================

 

共享库

 

 

共享库使用:程序第一次执行或者第一次调用某个库函数时,用动态连接方法将程序与共享库函数相连接。这减少了每个可执行文件的长度,但增加了一些运行时间开销。——只在程序运行时才载入内存的,在编译过程中只简单的引用。

 

共享库的优点是库函数的新版本代替老版本而无需对使用该库的程序重新连接编辑。

 

目录结构

 

[www@zhoubc src]$ tree
.
|-- pop.c
`-- push.c
 

 

1)编译、汇编到目标代码,不进行链接

 

[www@zhoubc src]$ gcc -fPIC -c pop.c push.c 

[www@zhoubc src]$ tree
.
|-- pop.c
|-- pop.o
|-- push.c
`-- push.o

 参数说明:

       -f 后面跟一些编译选项.

             PIC 是其中一种,表示生成位置无关代码

        -fPIC:生成与位置无关的代码.因为共享库链接的时候都是使用的是相对地址,所以必须指定这一项。

 

2)建立共享库

[www@zhoubc src]$ gcc -shared -o libstack.so pop.o push.o
[www@zhoubc src]$ tree
.
|-- libstack.o
|-- pop.c
|-- pop.o
|-- push.c
`-- push.o
 

参数说明

    -shared:代表要建立共享库.

 

3)测试共享库

 

[www@zhoubc src]$ gcc main.c -L./ -lstack 

 -L. 选项,编译器可以在./目录下找到libstack.so文件

 

 执行

[www@zhoubc src]$ ./a.out 
./a.out: error while loading shared libraries: libstack.so: cannot open shared object file: No such file or directory

 

  错误解决

[www@zhoubc src]$ ldd a.out 
	linux-gate.so.1 =>  (0x00d59000)
	libstack.so => not found
	libc.so.6 => /lib/libc.so.6 (0x00a68000)
	/lib/ld-linux.so.2 (0x00a44000)

    ldd 命令查看可执行文件依赖于哪些共享库.

         ldd模拟运行一遍a.out,在运行过程中做动态链接,从而得知这个可执行文件依赖于哪些共享库,每个共享库都在什么路径下,加载到进程地址空间的什么地址.

 

  共享库路径的搜索顺序:

  •    首先在环境变量LD_LIBRARY_PATH 所记录的路径中查找。
  •    然后从缓存文件/etc/ld.so.cache 中查找。这个缓存文件由ldconfig 命令读取配置文件/etc/ld.so.conf 之后生成.
  •    如果上述步骤都找不到,则到默认的系统路径中查找,先是/usr/lib然后是/lib

解决问题:

    <1>指定搜索路径

[www@zhoubc src]$LD_LIBRARY_PATH=./

    <2>把绝对路径添加到/etc/ld.so.cache中,然后运行ldconfig——常用方法

    <3>把so文件拷到/usr/lib或/lib目录。

    <4>在编译可执行文件的时候就把so的路径写死在可执行文件中。

[www@zhoubc src]$ gcc main.c -g -L./ -lstack -Wl,-rpath,./

 

     -Wl,-rpath,./ 表示-rpath ./ 是由gcc 传递给链接器的选项,表示搜索路径.

     -Wl,option代表把选项option传给链接器.

 

 

 

 

=========================================================================

 

 

 

共享库和静态库

 

 

链接共享库和链接静态库区别 :

      链接共享库 只是指定了动态链接器和该程序所需要的库文件,并没有真的做链接,可执行文件调用的库函数仍然是未定义符号,要在运行时做动态链接 。——在编译和加载的时候都需要,没有真正编译进可执行文件。

     链接静态库 链接器会把静态库中的目标文件取出来和可执行文件真正链接在一起.——只在编译的时候需要

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值