关于动态库
静态库与动态库
静态库在程序的链接阶段被复制到了程序中,和程序运行的时候没有关系。
动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入。
静态库编译
g++ -I../include -O0 -g3 -Wall -c -fPIC -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<"
g++ -L../lib -L/usr/local/unixodbc/lib -shared -o "libkbodbcpro.so"
这里第一句是将.c
文件生成.o
文件,第二句是将.o
文件链接生成.so
动态库文件。
其他的不用管,注意-fPIC
和 -shared
这两个参数是生成动态文件的关键参数
參数 -fPIC
作用:
当使用.so等类的库时,当遇到多个可运行文件共用这一个库时, 在内存中,这个库就不会被复制多份,让每一个可运行文件一对一的使用,而是让多个可运行文件指向一个库文件,达到共用.
宗旨:节省了内存空间,提高了空间利用率.
动态库链接
编译时
动态库的调用关系可以在需要调用动态库的程序编译时,通过g++的-L和-l命令来指定。例如:程序test启动时需要加载目录/root/src/lib中的libtest_so1.so动态库,编译命令可照如下编写执行:
g++ -g -o test test.cpp –L/root/src/lib –ltest_so1
代码中打开动态库
include <dlfcn.h>
dlopen
函数定义:
void * dlopen( const char * pathname, int mode);
函数定义:
按mode模式打开pathname指定的动态库。
返回值:
打开错误返回NULL
成功,返回库引用
编译时候要增加 -ldl (指定dl库)
比如
gcc test.c -o test -ldl
例:
int main(void)
{
void *handle = NULL;
char *myso = "./mylib.so";
if ((handle = dlopen(myso, RTLD_NOW)) == NULL) {
printf("dlopen - %sn", dlerror());
exit(-1);
}
return 0;
}
dlclose
函数原型为:
int dlclose (void *handle);
函数描述:
dlclose用于关闭指定句柄的动态链接库,只有当此动态链接库的使用计数为0时,才会真正被系统卸载。
dlsym
void *dlsym(void * handle,const char * symbol)
根据 动态链接库 操作句柄(handle)与符号(symbol),返回符号对应的地址。
使用这个函数不但可以获取函数地址,也可以获取变量地址。
handle
:由dlopen打开动态链接库后返回的指针
symbol
:要求获取的函数或全局变量的名称
返回值:
void *
指向函数的地址,供调用使用。
dlerror
函数原型:
char *dlerror(void);
函数描述:
当动态链接库操作函数执行失败时,dlerror可以返回出错信息,返回值为NULL时表示操作函数执行成功。