zoukankan      html  css  js  c++  java
  • 动态、静态库的创建和使用

    1、linux库的概念

    库是一种软件组件技术,库里面封装了数据和函数,提供给用户程序调用。库的使用可以使程序模块化,提高程序的编译速度,

    实现代码重用,使程序易于升级。因此,对于软件开发人员,掌握这项技术是十分必要的。window系统本身提供并使用了大量的库,

    包括静态链接库(.lib)和动态链接库(.dll)。类似的,linux系统也使用库。linux系统中,通常把库文件放在/usr/lib或/lib目录下。Linux库

    文件由前缀lib、库名以及后缀3部分组成,其中动态库以.so作为后缀,而静态库通常以.a作为后缀。

    在程序中使用静态库和动态库时,他们的载入顺序是不一样的。静态库的代码在编译时就拷贝到应用程序中,因此当多个应用程序

    同时引用一个静态库函数时,内存中将会有调用函数的多个副本。这样的优点是节省编译时间。而动态库是在程序运行开始后调用

    库函数时才被载入,被调函数在内存中只有一个副本,并且动态库可以在运行程序期间释放动态库所占用的内存,腾出空间供其他

    程序使用。

     

    2、静态库的创建和使用

    创建静态库的步骤:

    (1)在一个头文件中声明静态库所导出的函数

    (2)在一个源文件中实现静态库所导出的函数

    (3)编译源文件,生成可执行代码

    (4)将可执行代码所在的目标文件加入到某个静态库中,并将静态库拷贝到系统默认的

    存放库文件的目录下。

    实例:

    mylib.h中存放的是静态库提供给用户使用的函数的声明,mylib.c实现了mylib.h中声明的函数

    头文件

    #ifndef  _mylib_h_

    #define  _mylib_h_

    void welcome();

    void outstring(const char  *str);

    #endif

    源文件:

     #include<stdio.h>

    #include "mylib.h"

    void welcome()

    {

      printf("welcome to lib ");

    }

    void outstring(const char  *str)

    {

      if ( !str )

      {

        printf("%s ", str);

      }

    }

    编译mylib.c生成目标文件

     gcc -o mylib.o -c mylib.c

    将目标文件加入到静态库中,静态库为libmylib.a

    ar  rcs libmylib.a  mylib.o

    将静态库拷贝到linux的库目录(/usr/lib或/lib)下:(也可不拷贝,在编译时指定静态库的路径)

    cp  libmylib.a     /usr/lib/libmylib.a 

    以下为调用库函数的测试程序test.c

    #include "lib.h"


    int main()
    {
      weclome();

      outstring("haha");
      return 0;
    }

    编译test.c生成可执行文件

    gcc -o  main   test.c   -lmylib    -L .

    注意: -lmylib 中 -l 为选项。 mylib为库名。 mylib是 “libmylib.a”的中间部分,linux下约定所有库

    都以前缀lib开始,静态库以 .a结尾。动态库以.so结尾。在编译程序时,无需带上前缀和后缀。

    linux下,可以使用ar命令来创建和修改静态库。

    ar   rcs     libmylib.a   file1.o    file2.o

    该命令将目标代码file1.o   和 file2.o 加入到静态库libmylib.a中,加入时如果静态库libmylib.a不存在,则会

    自动创建一个静态库。rcs是命令ar的选项。

    以下是ar命令 的使用格式。

    ar [emulation options] [-]{dmpqrstx}[abcDfilMNoPsSTuvV]      库名  库中的成员文件名

    其中的 - 不是必需的,  “dmpqrstx” 这些字母在每个命令中只能有一个且必须有一个

    ”abcDfilMNoPsSTuvV“中的字母在每个命令中可以有0到多个。

    常用选项含义如下:

    d:从库中删除成员文件

    m:

    p:

    q:

    r:

    t:

    x:

    a:

    b:

    c:创建一个库

    i:

    l:

    s:无论ar命令是否修改了库内容,都强制重新生成库符号表

    u:

    v:用来显示操作的附件信息

    V:显示ar的版本信息

     

    3、动态库的创建和使用

    在linux环境下,可以很方便地创建和使用动态链接库。只要在编译函数库源程序时加上 -shared选项即可,这样所生成的可执行程序就为动态链接库。

    从某种意义上讲,动态链接库也是一种可执行程序。

    按一按规则,动态链接库以.so后缀。下面命令把mylib.c程序创建成了一个动态库:

    gcc  -fPIC  -o  lib.o  -c  lib.c
    gcc  -shared  -o  libmylib.so  lib.o

    也可以直接使用一条指令:

    gcc  -fPIC   -shared  -o   libmylib.so  lib.c

    动态链接库创建后就可以使用了。

    两种方法调用动态链接库中的函数:

    (1)像使用静态库一样,通过gcc命令调用

    gcc     -o   main   test.c     ./ libmylib.so

    gcc -o main test.c -lmylib -L .

    需要把 libmylib.so   放入到 系统指定的目录下(/etc/ld.so.conf 配置这个路径)

    执行:

    ./main

    (2)通过系统调用来使用动态链接库

    #include <dlfcn.h>

    void *dlopen(const char *filename, int flag);

    打开指定名字的动态链接库,并返回一个句柄

    char *dlerror(void);

    动态链接库中的函数执行失败时,dlerror返回出错信息;若执行成功,则返回NULL

    void *dlsym(void *handle, const char *symbol);

    根据动态链接库的句柄与函数名,返回函数名对应的函数的地址

    int dlclose(void *handle);

    关闭动态链接库,handle是调用dlopen函数返回的句柄。

    Link with -ldl. 

    以上的函数在库中,编译调用这些库函数的程序需要 链接库   -ldl

    ------------------------------------------------------

    dlopen函数的参数flag可取的值有:

    RTLD_LAZY:需要在dlopen返回前,对于动态库中存在的未定义的变量(如外部变量extern,也可以是函数)不执行解析,也就是

    不解析这个变量的地址

    RTLD_NOW:需要在dlopen返回前,解析出所有未定义符号,如果解析不出来,在dlopen会返回NULL,错误为:: undefined symbol: xxxx.......

    RTLD_GLOBAL:使库中被解析出来的变量在随后的其他链接库中也可以使用,即全局有效。

    实例:

    #include <stdio.h>
    #include <dlfcn.h>
    #include <stdlib.h>
    
    int main()
    {
        void *handle;
        char *error;
        void (*welcome)();
    
        if ((handle = dlopen("./libmylib.so", RTLD_LAZY)) == NULL)
        {
            printf("dlopen error:");
            exit(1);
        }
    
        welcome = dlsym(handle, "weclome");
    
        if ((error =dlerror()) != NULL)
        {
            perror("dlerror error:");
            exit(1);
        }
    
        welcome();
        
        dlclose(handle);
    
    
        return 0;
    }

    编译:

    gcc -o main test.c -ldl

    ./main

    程序成功调用了动态链接库libmylib.so中的welcome函数。通过在程序中调用系统函数来使用动态链接库时,

    动态链接库要指定所在的路径。

    注意:这种调用方式,不要把动态库拷贝到系统指定的动态库目录下。

  • 相关阅读:
    设置文本框的 placeholder 的颜色
    CSS单行文字超出省略
    【持续跟新】剑指Offer_Java实现
    Android必修课-Activity生命周期
    如何查看Android的jks签名的MD5
    Flutter 文字边框/边框颜色
    Flutter initState 初始化调用 Provide报错
    flutter 系统通知栏Demo 基于flutter_local_notifications: ^1.4.1
    # Flutter学习笔记(一)
    一个技术人毕业到就业的思考
  • 原文地址:https://www.cnblogs.com/zhangxuan/p/6760586.html
Copyright © 2011-2022 走看看