文章目录
关于gcc的使用方法,可以参考下面链接的博客:
Linux下gcc编译过程解读(含代码示例)&& gcc教程
1.库的概念Windows库
Windows系统本身提供并使用了大量的库;
Linux库
Linux系统一般将库文件存放在/usr/lib或/lib目录下,
·Linux库文件名组成:前缀lib+库名+后缀(由3部分组成)
—————————————————————————————
动态库:以.so为后缀
静态库:一般以.a或.la为后缀。
二、动态库和静态库的区别 1、加载顺序不同
静态库的代码在编译时被复制到应用程序中,因此当多个应用程序同时引用静态库函数时,会在显存上调用该函数的多个副本。 优点是节省编译时间。
动态库是在程序开始运行并调用库函数后加载的。 被调用函数在显存中只有一份,但动态库可以在程序运行过程中释放动态库占用的显存。
2.大小和共享的区别
静态链接库是在程序编译时加载的。 这样的可执行文件会比较大,无法共享; 动态链接库在程序执行时被加载,并且可以共享。
3、库函数调用的差异
静态链接是指将要调用的函数或过程链接到可执行文件中,成为可执行文件的一部分。
动态链接调用的函数代码并不复制到应用程序的可执行文件中,而只是在其中添加被调用函数的描述信息(常常是一些重定位信息)。 只有当应用程序被放入显存并开始运行时,在linux的管理下typescript共享库,应用程序与对应的.so之间的链接关系才建立起来。 当要执行被调用的动态库中的函数时,根据链接形成的重定位信息执行动态库中相应的函数代码。
三、静态库的创建和使用 1、创建静态库的步骤:在头文件中声明静态库导入的函数,在源文件中实现静态库导入的函数,编译源文件,并生成可执行代码(不带Link) 将可执行代码所在的目标文件添加到静态库中,并将静态库复制到系统默认存储库目录(/usr/lib 或/lib)中。 (1) ar命令的使用方法
ar 命令的可用选项:
选项 说明
从库中删除成员
在终端上复制指定的库手成员
向库中添加新的成员文件,如果存在则替换该成员文件; 默认情况下,新的成员文件被放置在库的末尾
显示库的成员文件列表
将新成员文件放在库的现有成员前面
创建一个库
将新的成员文件放在库的现有成员之上
强制重建库符号表,无论 ar 命令是否更改了库内容
从库中提取一个成员文件。如果没有指定成员文件,则提取库中的所有文件
(2)生成静态库实例
(1)头文件mylib.h——声明静态库导入的函数
#ifndef _mylib_H_ //如果没有定义此标识符,编码以下程序
#define _mylib_H_ 1
void welcome();
void outstring (const char * str);
#endif
(2)头文件对应的源文件mylib.c——实现静态库导入的函数
#include “mylib.h”
#include
void welcome() {
printf (“welcome to libmylibn”);
}
void outstring(const char * str) {
if (str !=NULL)
printf (“%s”,str);
}
(3)编译mylib.c生成目标文件:
#gcc –omylib.o –cmylib.c
注意:-c只编译不生成可执行文件,-o指定文件名
有关如何使用 gcc 的更多信息,请参阅下面链接的博客:
Linux下gcc编译过程解读(含代码示例)&& gcc教程
(4)将目标文件添加到静态库中,静态库为libmylib.a
#arrcslibmylib.amylib.o
参数说明:
/*r—向库中添加新的成员文件typescript共享库,如果要添加的成员文件存在,则替换它 默认情况下,新的成员文件被丢弃在库的末尾
/*c 创建一个库
/*s 强制重新生成库符号表,无论 ar 命令是否更改了库内容
(5)将静态库复制到linux的库目录(/usr/lib或/lib)
#cplibmylib.a /usr/lib/libmylib.a
这里生成了静态库,让我们尝试将它与程序链接起来。
2.调用静态库的测试程序
简而言之:使用 .c 源文件在编译时进行静态链接
(1)调用静态库的测试程序:test.c
#include “mylib.h”
#include
int main()
{
printf (“create and use library:n”);
welcome(); //静态库中的函数原型
outstring(“It’s successfuln”); //静态库中的函数原型
}
(2) 编译使用库函数的程序
#gcc –otesttest.c –lmylib
参数说明:
(1)选项l为链接选项,表示链接时将静态库链接到源程序中
(2)在Linux中,约定所有库都以前缀lib开头,静态库以.a结尾,动态库以.so结尾。 编译时不需要带前缀(lib)和后缀(.a)。
四、动态库的创建和使用
注意:动态库没有存档,必须在编译过程中生成符号表
1.动态库的创建
#gcc –fPIC-omylib.o-cmylib.c(生成符号表)
#gcc–shared-olibmylibs.somylib.o(避免双重加载)
或者直接使用命令也可以
#gcc–fPIC–shared–olibmylibs.somylib.c(-c和.o后缀文件名可以省略)
将生成的静态库复制到/usr/lib或/lib目录下
#cplibmylibs.so /usr/lib/libmylibs.so
2.动态库的使用
(1)由gcc命令调用
#gcc –otesttest.c -lmylibs
(2)通过调用系统函数使用动态链接库
在:
dlopen函数的参数flag的可能值为:RTLD_LAZY、RTLD_NOW、RTLD_GLOBAL:
RTLD_LAZY:在dlopen()返回之前,不解析动态库中未定义的变量,即不解析这个变量的地址 RTLD_NOW:在dlopen返回之前,解析每个未定义变量的地址,如果解析不解析下来,dlopen会返回NULL,错误为“Undefinedsymbol:” RTLD_GLOBAL: 使库中解析的变量在其他链接库中也可用,即全局有效 3、通过调用系统使用动态链接库的实例功能
创建 testo.c 文件:
#include
#include
int main (void)
{
void *handle;
char *error;
void (*welcome)(); //要变成指针函数来用(由符号表引出的指针)
if ((handle = dlopen(“/usr/lib/libmylibs.so”, RTLD_LAZY) == NULL)
{
printf (“dlopen errorn”);
exit(1);
}
welcome = dlsym(handle, “welcome”);
if ((error = dlerror()) != NULL)
{
printf (“dlsym error n”);
exit(1);
}
welcome ();
dlclose (handle);
exit(0);
}
编译:#gcc –otestsotestso.c-ldl
其中:-ldl表示dlopen等函数所在的库类型