美文网首页想法
你的动态库还在报错?

你的动态库还在报错?

作者: ElephantKing | 来源:发表于2019-11-06 14:11 被阅读0次

    动态库和静态库

    静态库:仅仅是一组目标文件的集合,简单的包装到一起,起到一个文件夹的作用,比如你的main.c分别用到h1.c h2.c h3.c里的函数,自然地h1.c h2.c h3.c各自都可以编译为对应的.o文件,虽然这里只有三个,但实际情况下可以有很多,那么你在编译main.c这个文件时是不是需要这样写gcc main.c h1.o h2.o h3.o -o main,如果这样的.o文件太多,你就会崩溃,这个时候如果能将这些.o文件打包在一起,用起来就方便多了。比如将h1.o h2.o h3.o打包为libhelp.a静态库,在使用的时候只需要gcc main.c -lhelp,通过这种方式,能简化一些,而且在链接过程中,已将库中的代码链接到可执行文件main中,之后main的运行就不再需要libhelp.a这个文件了。
    动态库:和静态库不一样,使用动态库的程序,仅在运行时才去链接动态库中的代码,且程序共享动态库的代码,每个可执行程序和动态库之间保存一份函数地址表,运行时查表去执行相应代码,所以动态库在程序运行时必须在场。

    自己生成动态库和静态库

    生成静态库:

    // static_help.h
    #ifndef __STATIC_HELP_H_
    #define __STATIC_HELP_H_
    int static_help();
    #endif
    // static_help.c
    #include <stdio.h>
    #include "static_help.h"
    int static_help()
    {
      printf("static help\n");
      return 10;
    }
    

    上述两个文件,我们用命令把他制作为静态库,由于静态库是.o的集合,所以我们需要先编译出.o文件。通过下面的命令我们就能得到静态库文件libstatic_help.a

    gcc -c static_help.c -o static_help.o
    ar -rc libstatic_help.a static_help.o
    

    生成动态库:

    // dynamic_help.h
    #ifndef __DYNAMIC_HELP_H_
    #define __DYNAMIC_HELP_H_
    int dynamic_help();
    #endif
    // dynamic_help.c
    #include <stdio.h>
    #include "dynamic_help.h"
    int dynamic_help()
    {
      printf("dynamic help\n");
      return 100;
    }
    
    gcc -fPIC -shared dynamic_help.c -o libdynamic_help.so
    

    如何使用第三方库

    现在我们来看一下文件的位置:

    库文件的位置

    我们main.c的代码如下:

    #include <stdio.h>
    #include "static_help.h"
    #include "dynamic_help.h"
    
    int main()
    {
      static_help();
      dynamic_help();
      return 0;
    }
    

    通常情况下我们的静态库和动态库和我们的代码目录不在一起,所以在编译的时候我们需要指定库的目录,可以这么写makefile文件

    #指定库对应的头文件位置,最好使用绝对路径,而不是相对路径
    INCLUDE=-I./dynamic_lib -I./static_lib
    all:main
    #用-L./dynamic_lib指定库的位置,最好用绝对路径
    main:main.c
      gcc $(INCLUDE) main.c -L./dynamic_lib/ -L./static_lib/ \
      -ldynamic_help -lstatic_help -o main
    .PHONY:clean
    clean:
      rm main
    

    这样就编译好了我们的可执行程序main,接下来编写一个脚本run.sh来运行我们的代码。

    #运行时,仅需要指定动态库的位置
    export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./dynamic_lib/
    ./main
    
    #需要给这个脚本加上可执行权限:chmod 770 run.sh
    #执行脚本:./run.sh
    #执行结果:
    #static help
    #dynamic help
    

    常见库报错

    使用第三方库的时候经常会遇到以下这几种错误,这里单独列出来,也许,你在复盘上面的代码就会遇到。

    1. 找不到对于库的头文件,fatal error: static_help.h: 没有那个文件或目录,遇到这个错误说明你的代码包含了库的头文件,但是编译的时候找不到,需要在makefile里用-I./dynamic_lib这样的方式指定头文件位置。
    2. 找不到库文件 ,/usr/bin/ld: 找不到 -ldynamic_help
      collect2: error: ld returned 1 exit status
      ,遇到这个错误说明你使用了库里的函数,但是在编译的时候找不到函数地址,需要在makefile里用-L./dynamic_lib这样的方式指定。
    3. 找不到函数地址,main.c:(.text+0x14):对‘dynamic_help’未定义的引用,遇到这种情况说明,代码里使用了库函数,但是未把库引用进来,需要使用-ldynamic_help把库引入。
    4. 在你编译成功后,运行程序时,./main: error while loading shared libraries: libdynamic_help.so: cannot open shared object file: No such file or directory,说明你的执行环境里找不到动态库,换句话说你用了不在默认库路径下的库。需要用LD_LIBRARY_PATH来指定,在我们上面的栗子中就是语句export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./dynamic_lib/干的事情。

    相关文章

      网友评论

        本文标题:你的动态库还在报错?

        本文链接:https://www.haomeiwen.com/subject/xcxubctx.html