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函数。通过在程序中调用系统函数来使用动态链接库时,

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

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

  • 相关阅读:
    dotnet 新项目格式与对应框架预定义的宏
    dotnet 线程静态字段
    dotnet 线程静态字段
    dotnet 通过 WMI 拿到显卡信息
    dotnet 通过 WMI 拿到显卡信息
    dotnet 通过 WMI 获取指定进程的输入命令行
    dotnet 通过 WMI 获取指定进程的输入命令行
    dotnet 通过 WMI 获取系统信息
    dotnet 通过 WMI 获取系统信息
    PHP show_source() 函数
  • 原文地址:https://www.cnblogs.com/zhangxuan/p/6760586.html
Copyright © 2011-2022 走看看