星期二, 一月 22, 2008

C static && dynamic library

首先看如下几个 C 源文件:
roc@ulfs:~/c$ cat main.c
#include
// #include "mod1.h"

void main() {
printf("Hello world: %d\n", func(8));
return;
}

roc@ulfs:~/c$ cat mod1.h
#include
// #include "mod2.c"
#include "mod2.h"

roc@ulfs:~/c$ cat mod2.h
int func(int i);

roc@ulfs:~/c$ cat mod2.c
#include

int func(int i) {
int I = i*i;
printf("i == %d\n", i);
return I;
}
然后进行编译并运行:
roc@ulfs:~/c$ gcc main.c mod2.c
roc@ulfs:~/c$ gcc main.c mod2.c
main.c: In function 'main':
main.c:4: warning: return type of 'main' is not 'int'
roc@ulfs:~/c$ ./a.out
i == 8
Hello world: 64
此时完全不需要头文件,编译器直接链接了。那么究竟何时需要头文件呢?

是不是和动态连接库有关呢?首先了解一下动态链接库:
roc@ulfs:~/c$ gcc -c main.c
roc@ulfs:~/c$ gcc -c mod2.c
roc@ulfs:~/c$ gcc -shared -o libmod2.so mod2.o
roc@ulfs:~/c$ gcc -shared -o libmod2.so.1 mod2.c
roc@ulfs:~/c$ diff libmod2.so libmod2.so.1
// 显示两个文件是完全一样的
roc@ulfs:~/c$ file libmod2.so
libmod2.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), not stripped
roc@ulfs:~/c$ file mod2.o
mod2.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped
// 此时是两种不同的文件
然后尝试用两种方式编译:
roc@ulfs:~/c$ gcc -o dynamic.out main.o libmod2.so
roc@ulfs:~/c$ gcc -o dynamic.out.1 main.c libmod2.so
main.c: In function 'main':
main.c:4: warning: return type of 'main' is not 'int'
roc@ulfs:~/c$ diff dynamic.out dynamic.out.1
// 两个文件也是一样的
然后运行:
roc@ulfs:~/c$ ./dynamic.out
./dynamic.out: error while loading shared libraries: libmod2.so: cannot open shared object file: No such file or directory
roc@ulfs:~/c$ sudo vi /etc/ld.so.conf
...
/home/roc/c
# ADD THIS LINE
# 以确保运行时可以找到这个共享库,应该也可以使用 LD_LIBRARY_PATH 环境变量
roc@ulfs:~/c$ sudo ldconfig
roc@ulfs:~/c$ ./dynamic.out
i == 8
Hello world: 64
// 可以正确运行
// 此时仍然不需要使用头文件


# ******
roc@ulfs:~/c$ gcc -static -o static.out main.o libmod2.so
/usr/bin/ld: attempted static link of dynamic object `libmod2.so'
collect2: ld returned 1 exit status

# ****** ???

如果我不使用 libmod2.so 文件名,而使用 mod2.so 文件名会如何呢?
roc@ulfs:~/c$ gcc -shared -o mod2.so mod2.o
roc@ulfs:~/c$ diff mod2.so libmod2.so
roc@ulfs:~/c$ gcc -o dy.out main.o mod2.so
roc@ulfs:~/c$ ./dy.out
./dy.out: error while loading shared libraries: mod2.so: cannot open shared object file: No such file or directory
roc@ulfs:~/c$ LD_LIBRARY_PATH=. ./dy.out
i == 8
Hello world: 64
使用 libmod2.so 这种形式的文件名是为了在 gcc 上使用 -l 参数时更方便,能够直接找到相关的库而不需要指定具体的文件:

roc@ulfs:~/c$ gcc -o dynamic.out main.o -lmod2
/usr/bin/ld: cannot find -lmod2
collect2: ld returned 1 exit status
roc@ulfs:~/c$ gcc -o dynamic.out main.o -L. -lmod2
# 或者:
roc@ulfs:~/c$ LIBRARY_PATH=. gcc -o dynamic.out main.o -lmod2
使用 -L 或 LIBRARY_PATH 是为了保证在编译的时候能够找到需要的共享库文件。

到目前为止,没有看到必须要使用头文件的地方!

另外,可以了解一下 lib*.a 文件,它实际上是(archive)的简写,和 tar 文件非常类似,不过 tar 最初是使用磁带的,而 ar 直接将磁盘上的 *.o 对象文件打包到 *.a 档案文件中,因此可以供静态链接使用。可以用 ar -t 命令查看一个 *.la 文件。

gcc -o dynamic.out main.c libmod2.a ??????

没有评论: