当前位置: 技术问答>linux和unix
动态库理解的疑惑
来源: 互联网 发布时间:2017-03-22
本文导语: 我现在明白了动态库和静态库的区别是在调用的时候,动态库是在使用的时候才进行调用,其中的代码并没有添加到生成的可执行文件中;而静态库被添加到生成的可执行文件中,所以最终生成的可执行文件比较大。...
我现在明白了动态库和静态库的区别是在调用的时候,动态库是在使用的时候才进行调用,其中的代码并没有添加到生成的可执行文件中;而静态库被添加到生成的可执行文件中,所以最终生成的可执行文件比较大。
我现在的问题是:
问题1、动态库可不可以理解成是把一个函数打包成一个.so文件呢?
举一个例子就是我有一个实现阶乘的函数放到文件factorial.cpp文件中:
问题2:我如果把实现阶乘的函数封装成一个动态库的话,是不是只是把factorial.cpp文件打包成一个后缀是.so的文件,然后以后想使用的时候,还需要使用与此有关的头文件factorial.h 呢?
问题3:还有,如果实现阶乘的函数中间要调用了一个乘法函数
那么在生成阶乘函数的动态库的时候,我们是不是必须要还要添加乘法的函数呢?
如下:
问题4:如果我们的乘法函数也是一个动态库的话,那么我们在生成阶乘动态库的时候,还需要添加乘法的动态库。我想问的是:我们生成的动态库中,是不是也把乘法的动态库加进去了?还是只是相当于在生成的阶乘动态库中添加了一个指向乘法动态库的路径,以后运行的时候,如果使用乘法功能的话,再去找乘法的动态库。
谢谢,这个我一直迷糊,希望大家可以不吝赐教!谢谢!
我现在的问题是:
问题1、动态库可不可以理解成是把一个函数打包成一个.so文件呢?
举一个例子就是我有一个实现阶乘的函数放到文件factorial.cpp文件中:
/* factorial.cpp */
double factorial(int n){}
问题2:我如果把实现阶乘的函数封装成一个动态库的话,是不是只是把factorial.cpp文件打包成一个后缀是.so的文件,然后以后想使用的时候,还需要使用与此有关的头文件factorial.h 呢?
问题3:还有,如果实现阶乘的函数中间要调用了一个乘法函数
/* multi.cpp */
double multi(int n){}
那么在生成阶乘函数的动态库的时候,我们是不是必须要还要添加乘法的函数呢?
如下:
CC=g++
factorial.so:factorial.o multi.o
$(CC) -shared -o $@ $^
factorial.o:factorial.h multi.h factorial.cpp
$(CC) -fPIC -c $^
multi.o:multi.h multi.cpp
$(CC) -fPIC -c $^
clean:
rm *.o
问题4:如果我们的乘法函数也是一个动态库的话,那么我们在生成阶乘动态库的时候,还需要添加乘法的动态库。我想问的是:我们生成的动态库中,是不是也把乘法的动态库加进去了?还是只是相当于在生成的阶乘动态库中添加了一个指向乘法动态库的路径,以后运行的时候,如果使用乘法功能的话,再去找乘法的动态库。
谢谢,这个我一直迷糊,希望大家可以不吝赐教!谢谢!
|
看你发了两次帖子,分好多,我也认真的上网查阅了一遍,作答如下,欢迎拍砖~
>问题1、动态库可不可以理解成是把一个函数打包成一个.so文件呢?
可以。还可以扩展下(在linux下),动态库可以是把很多函数打包成一个.so文件;静态库可以是把很多个函数打包成一个.a文件。
>问题2:我如果把实现阶乘的函数封装成一个动态库的话,是不是只是把factorial.cpp文件打包成一个后缀是.so的文件,然后以后想使用的时候,还需要使用与此有关的头文件factorial.h 呢?
需要。
这个问题是一个编译的常识,编译器在编译一个符号(函数、变量等)的时候,首先是要看看这个符号在符号表里边定义了没有,如果没有定义,那么就会报错说找不到这个符号。为什么需要factorial.h 呢?那是因为factorial.h文件里有double factorial(int n)这个函数的声明,编译器在看到有#include "factorial.h"时就认为factorial函数(就是上边说的符号)已经定义,这样在编译阶段就可以通过了。
这说起来比较绕口,望楼主多了解下程序的执行过程:预处理->编译(词法、语法、语义分析)->汇编->链接->装载执行。
问题3:还有,如果实现阶乘的函数中间要调用了一个乘法函数,那么在生成阶乘函数的动态库的时候,我们是不是必须要还要添加乘法的函数呢?
是需要的。
这就跟第二个问题中的程序要调用factorial函数是一个道理。
问题4:如果我们的乘法函数也是一个动态库的话,那么我们在生成阶乘动态库的时候,还需要添加乘法的动态库。我想问的是:我们生成的动态库中,是不是也把乘法的动态库加进去了?还是只是相当于在生成的阶乘动态库中添加了一个指向乘法动态库的路径,以后运行的时候,如果使用乘法功能的话,再去找乘法的动态库。
后一种解释是对的:只是相当于在生成的阶乘动态库中添加了一个指向乘法动态库的路径,以后运行的时候,如果使用乘法功能的话,再去找乘法的动态库。
>问题1、动态库可不可以理解成是把一个函数打包成一个.so文件呢?
可以。还可以扩展下(在linux下),动态库可以是把很多函数打包成一个.so文件;静态库可以是把很多个函数打包成一个.a文件。
>问题2:我如果把实现阶乘的函数封装成一个动态库的话,是不是只是把factorial.cpp文件打包成一个后缀是.so的文件,然后以后想使用的时候,还需要使用与此有关的头文件factorial.h 呢?
需要。
这个问题是一个编译的常识,编译器在编译一个符号(函数、变量等)的时候,首先是要看看这个符号在符号表里边定义了没有,如果没有定义,那么就会报错说找不到这个符号。为什么需要factorial.h 呢?那是因为factorial.h文件里有double factorial(int n)这个函数的声明,编译器在看到有#include "factorial.h"时就认为factorial函数(就是上边说的符号)已经定义,这样在编译阶段就可以通过了。
这说起来比较绕口,望楼主多了解下程序的执行过程:预处理->编译(词法、语法、语义分析)->汇编->链接->装载执行。
问题3:还有,如果实现阶乘的函数中间要调用了一个乘法函数,那么在生成阶乘函数的动态库的时候,我们是不是必须要还要添加乘法的函数呢?
是需要的。
这就跟第二个问题中的程序要调用factorial函数是一个道理。
问题4:如果我们的乘法函数也是一个动态库的话,那么我们在生成阶乘动态库的时候,还需要添加乘法的动态库。我想问的是:我们生成的动态库中,是不是也把乘法的动态库加进去了?还是只是相当于在生成的阶乘动态库中添加了一个指向乘法动态库的路径,以后运行的时候,如果使用乘法功能的话,再去找乘法的动态库。
后一种解释是对的:只是相当于在生成的阶乘动态库中添加了一个指向乘法动态库的路径,以后运行的时候,如果使用乘法功能的话,再去找乘法的动态库。
|
在生成动态库的时候,当需要添加的函数是函数源码的话,是把函数源码放在一起打包;而当需要添加的函数是另一个动态库的话,只是加了一个路径,让刚生成的动态库在运行使用的时候,可以更快更准确的找到我们需要的另一个动态库。
==》 正确。动态库也可以依赖动态库。
动态库依赖在.so或者可执行程序里表现为一个路径。可以是相对路径,也可以是绝对路径。
readelf -d xxx 可以查看程序或者动态库依赖的其它动态库。
比如:
xxxxxx@Ubuntu:~$ readelf -d /lib/libpng12.so.0.42.0
Dynamic section at offset 0x22e74 contains 26 entries:
Tag Type Name/Value
0x00000001 (NEEDED) Shared library: [libz.so.1]
0x00000001 (NEEDED) Shared library: [libm.so.6]
0x00000001 (NEEDED) Shared library: [libc.so.6]
0x0000000e (SONAME) Library soname: [libpng12.so.0]
自己多找些so文件试试,就明白了。
==》 正确。动态库也可以依赖动态库。
动态库依赖在.so或者可执行程序里表现为一个路径。可以是相对路径,也可以是绝对路径。
readelf -d xxx 可以查看程序或者动态库依赖的其它动态库。
比如:
xxxxxx@Ubuntu:~$ readelf -d /lib/libpng12.so.0.42.0
Dynamic section at offset 0x22e74 contains 26 entries:
Tag Type Name/Value
0x00000001 (NEEDED) Shared library: [libz.so.1]
0x00000001 (NEEDED) Shared library: [libm.so.6]
0x00000001 (NEEDED) Shared library: [libc.so.6]
0x0000000e (SONAME) Library soname: [libpng12.so.0]
自己多找些so文件试试,就明白了。