linux下的.a和.so,对比windows下的lib和dll
【原文】http://blog.chinaunix.net/uid-66572-id-2688627.html
两种库
- Linux下的静态库以.a结尾(Winodws下为.lib)
- Linux下的动态库以.so 或 .so.y结尾,其中y代表版本号(Windows下为.dll),而且,Linux下的库必须以lib开头,用于系统识别(如:libjpeg.a libsdl.so)
静态库必要的目标代码的是在对程序编译的时候被加入到程序中,而运行时不再需要.a的库了
而动态库,则是在运行时转载
所以,动态链接的可执行代码比静态链接的可执行代码小的多
把一个源代码编译成.so:
gcc -shared -o libtry.so try.c
而要生成静态库:
gcc -c try1.c gcc -c try2.c ar cqs libtry.a try1.o try2.o(或 ar r libtry.a try1.o try2.o)
库的使用
静态库的使用
# gcc -c main.c -o main.o # gcc main.o -o name -L. -ltry (-l后面的名字就是我们上面生成的try库)
动态库的使用
动态库分为显式调用和隐式调用
1.显示调用
需要了解以下几个函数:
动态库分为显式调用和隐式调用
1.显示调用
需要了解以下几个函数:
const char *dlerror(void);
当动态链接库操作函数执行失败时,dlerror可以返回出错信息,为NULL时表示操作函数执行成功。
void *dlopen(const char *filename, int flag);
成功则返回为void*的句柄。flag可以为RTLD_LAZY(表明在动态链接库的函数代码执行时解决);RTLD_NOW(表明在dlopen返回前就解决所有未定义的符号,一旦未解决,dlopen将返回错误)。filename为动态库路径。
void *dlsym(void *handle, char *symbol);
dlsym根据动态链接库操作句柄(handle)与符号(实际上就是欲调用的函数名),返回符号对应的函数的执行代码地址。由此地址,可以带参数执行相应的函数。
dlsym根据动态链接库操作句柄(handle)与符号(实际上就是欲调用的函数名),返回符号对应的函数的执行代码地址。由此地址,可以带参数执行相应的函数。
int dlclose (void *handle); 参数为动态链接库的句柄。 显式调用动态链接库必须包含动态链接库功能接口dlfcn.h(包含dl系列函数的声明)和被调函数的声明。
看起来还比较简单,但是当你对动态链接库函数使用比较频繁的时候,就知道他的麻烦了,所以,不推崇。
2.隐式调用
所谓隐式调用,就是调用的时候直接使用动态库中的函数,并不区别对待。
但是在隐式调用的时候必须要让程序能找到你所调用的函数的所属动态库。
我们先来建立一个感性认识:
# more /etc/ld.so.conf 你会看到以下内容:
所谓隐式调用,就是调用的时候直接使用动态库中的函数,并不区别对待。
但是在隐式调用的时候必须要让程序能找到你所调用的函数的所属动态库。
我们先来建立一个感性认识:
# more /etc/ld.so.conf 你会看到以下内容:
/usr/kerberos/lib
/usr/X11R6/lib
/usr/lib/sane
/usr/lib/qt-3.1/lib
/usr/lib/mysql
/usr/lib/qt2/lib
/usr/local/lib
/usr/local/BerkeleyDB.4.3/lib
ld.so.conf是系统对动态链接库进行查找的路径配置文件,也就是说该文件是系统链接工具/usr/bin/ld查找动态链接库的地图,所以,要达到我们的目的有以下几种方法:
a.将自己的动态链接库文件拷到以上路径的目录下
# cp libwx.so.1 /usr/local/lib
b.将自己动态链接库文件的路径加入到该文件中
# vi /etc/ld.so.conf, 然后加入自己的路径(或pwd >>/etc/ld.so.conf)
(千万不要将>>写成>,前者是添加,后者是覆盖)
c.把当前路径加入环境变量LD_LIBRARY_PATH,其实就是/usr/bin/ld的环境变量
# export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
编译的时候:
# gcc -o try main.c libtry.so.1
如果没有让/usr/bin/ld知道你的动态链接库在哪,编译的时候就要告诉它:
# gcc -o try main.c /root/libtry.so.1 ( 或:# gcc -L/root/wx -o qqq main.c libmy.so.1)
-L指定动态链接库所在的目录,有时候用gcc还会碰到-I,-l,他们分别指定头文件的目录和所链接的动态链接库
# cp libwx.so.1 /usr/local/lib
b.将自己动态链接库文件的路径加入到该文件中
# vi /etc/ld.so.conf, 然后加入自己的路径(或pwd >>/etc/ld.so.conf)
(千万不要将>>写成>,前者是添加,后者是覆盖)
c.把当前路径加入环境变量LD_LIBRARY_PATH,其实就是/usr/bin/ld的环境变量
# export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
编译的时候:
# gcc -o try main.c libtry.so.1
如果没有让/usr/bin/ld知道你的动态链接库在哪,编译的时候就要告诉它:
# gcc -o try main.c /root/libtry.so.1 ( 或:# gcc -L/root/wx -o qqq main.c libmy.so.1)
-L指定动态链接库所在的目录,有时候用gcc还会碰到-I,-l,他们分别指定头文件的目录和所链接的动态链接库
# ldd try 用来查看可执行文件qqq的动态链接库的依赖关系
如
libjpeg.so.62 => /usr/lib/libjpeg.so.62 (0x00867000)
libSDL-1.2.so.0 => /usr/lib/libSDL-1.2.so.0 (0x0638a000)
libc.so.6 => /lib/tls/libc.so.6 (0x0046d000)
libm.so.6 => /lib/tls/libm.so.6 (0x00598000)
libdl.so.2 => /lib/libdl.so.2 (0x005bd000)
libasound.so.2 => /lib/libasound.so.2 (0x062e1000)
libX11.so.6 => /usr/X11R6/lib/libX11.so.6 (0x005d5000)
libXext.so.6 => /usr/X11R6/lib/libXext.so.6 (0x0069e000)
libpthread.so.0 => /lib/tls/libpthread.so.0 (0x006ae000)
/lib/ld-linux.so.2 (0x00450000)
如
libjpeg.so.62 => /usr/lib/libjpeg.so.62 (0x00867000)
libSDL-1.2.so.0 => /usr/lib/libSDL-1.2.so.0 (0x0638a000)
libc.so.6 => /lib/tls/libc.so.6 (0x0046d000)
libm.so.6 => /lib/tls/libm.so.6 (0x00598000)
libdl.so.2 => /lib/libdl.so.2 (0x005bd000)
libasound.so.2 => /lib/libasound.so.2 (0x062e1000)
libX11.so.6 => /usr/X11R6/lib/libX11.so.6 (0x005d5000)
libXext.so.6 => /usr/X11R6/lib/libXext.so.6 (0x0069e000)
libpthread.so.0 => /lib/tls/libpthread.so.0 (0x006ae000)
/lib/ld-linux.so.2 (0x00450000)
平常做项目可能不怎么用到这些,不过一定要掌握vs或者qt等IDE里面关于静态库和动态库的导入设置。