• 在Linux平台上如何使用接静态库和共享库


    1、Linux函数库介绍

    函数库可以看做是事先编写的函数集合,它可以与主函数分离,从而增加程序开发的复用性。Linux中函数库可以有3种使用的形式:静态、共享和动态

    1)         静态库的代码在编译时就已连接到开发人员开发的应用程序中

    2)         而共享库只是在程序开始运行时才载入;

    3)         动态库也是在程序运行时载入,但与共享库不同的是,动态库使用的库函数不是在程序运行使开始载入,而是在程序中的语句需要使用该函数时才载入动态库可以在程序运行期间释放动态库所占用的内存,腾出空间供其他程序使用。

    注:

    l          由于共享库和动态库没有在程序中包括库函数的内容,只是包含了对库函数的引用因此代码的规模比较小

    l          系统中可用的库大都存放在/usr/local/lib、/usr/lib、/lib、目录中。

    l          头文件大都放在/usr/include、/usr/local/include目录下。

    l          共享库的相关配置文件和管理命令如下:

    /etc/ld.so.conf:包含共享库的搜索位置。

    ldconfig:共享库管理工具,一般在更新了共享库之后要运行该命令。

    ldd:可以查看可执行文件所使用的共享库。

    l          库文件名由前缀lib和库名以及后缀组成,根据库的类型不同,后缀名也不一样。

    2、大量使用库文件的主要原因

    1)     为了便于编程,对于部分经常使用的函数,相应的开发语言都提供了对应的库文件支持。

    2)     隐藏具体的函数实现细节。程序员在使用库文件时,只需要包含所需要函数所在的头文件,而不必关心该函数的具体实现。对于商业软件来说,其知识产权也得到了一定的保护。

    3、使用这些库函数都有什么途径

             在任何编程环境中,库文件都是一些预先编译好的函数集合,这些函数以二进制代码形式存储在库文件中。用户要使用这些函数,只需要包含这些库文件即可。一般来说,要从库文件获得相应的函数有两种办法。

    1)         在编译时将库中相应函数的二进制映像代码直接拷贝到当前编译的程序中,当前程序是独立运行的。这种库我们叫做静态库,在Linux中,以.a为后缀的为静态库。

    2)         在编译时只引用库中相应函数的二进制映像代码的入口地址(不直接拷贝),该程序在运行时从共享库文件中读出该函数代码(这需要首先将共享库加载到内存中),从而间接引用,这种库我们称之为共享库,在Linux中,以libxxx.xo.x.x为格式命名。

    4、具体如何使用

    使用静态库、共享库和动态库三种类型的方法很相似,都是使用选项是“-l”(注意这里是小写的“L”)。该选项是用于指明具体使用的库文件。由于在Linux中函数库的命名规则都是以“lib”开头的,因此,这里的库文件只需填写lib之后的内容即可。如:有静态库文件libm.a,在调用时只需写作“-lm”;同样对于动态库文件libm.so;在调用时也只需写作“-lm”即可,其整体调用命令类似如下:

    [root@localhost gcc]# gcc -o dynamic –L /root/lq/testc/lib/ dynamic.o -lmydynamic

    那么,若系统中同时存在文件名相同的静态库文件和动态库文件时,该链接选项究竟会调用静态库文件还是动态库文件呢?经测试后可以发现,系统调用的是动态库文件,这是由于Linux系统中默认的是采用动态链接的方式。这样,若用户要调用含有同名动态库文件的静态库文件,则在“-l”后需要显示地写出包含后缀名的文件名,如:要调用libm.a库文件时就需写作“-llibm.a”。

     

    1)     如果你已经有一个静态库文件libhello.a,此库文件的头文件为libhello.h,其内容如下:

    #ifndef __libhello_H__

    #define __libhello_H__

    void print_hello(void);       //print hello world,this is library to console

    #endif /*__libhello_H__*/

             我们可以从上面的代码看出,头文件知道libhello.a库文件包含了print_hello()函数,其返回值类型和参数都为空。因此,在编写程序时,你只需要使用此函数(在包含头文件的前提下),而不用去管其具体实现细节。

             使用libhello.a库文件的示例程序main.c如下:

    #include "libhello.h"

    int main(int argc, char** argv)

    {

    print_hello(); //引用库函数

    return 0;

    }

             我们现在可以把main.c、libhello.a拷贝到同一目录下,进行编译:

    # gcc –o usehello_static usehello.c –lhello // 也可以直接用libhello.a,前面不用加横杠

    2)     如果你已经有了一个共享库文件libhello.so.0.0,我们这里得做两个符号链接(具体原因本人搞的不是很清楚):

    # ln –s libhello.so.0 libhello.so.0.0

    # ln –s libhello.so libhello.so.0

             我们可以将这三个文件拷贝到当前目录,此库文件libhello.so.0.0中定义了print_hello()函数。可以查看其头文件libhello.h,其中包含如下内容:

    #ifndef __libhello_H__

    #define __libhello_H__

    void print_hello(void);       //即对print_hello()函数进行了一次生命

    #endif /*__libhello_H__*/

             同样,我们也可以在main.c中引用该共享库文件中的函数,main.c内容如下:

    #include "libhello.h"

    int main(int argc, char** argv)

    {

    print_hello(); //引用库函数

    return 0;

    }

             然后采用以下命令编译连接(你可以把库文件libhello.so.0.0拷贝到当前目录或者系统/lib目录下):

    # gcc –Wall –g –c usehello.c –o usehello.o //usehello.o为二进制目标文件

    # gcc –g –o usehello_dynamic usehello.o –L ./ -lhello //红色标记的是专门用于引用共享库的命令”-L dir”

    生成可执行文件后,你可以用ldd命令可执行文件所使用的共享库:

    # ldd usehello_dynamic

             终端会提示:libhello.so.0 => not found,所以你要想让这个可执行文件运行时达到你预期的效果,你必须在其运行的同时将共享库加到库的搜索路径中去:

    # LD_LIBRARY_PATH = $(pwd) ./usehello_dynamic

    5、相关路径选项的简单介绍

    由于库文件的通常路径不是在系统默认的路径下,因此,首先要使用调用路径选项来指定相关的头文件或者库文件的位置,这里讲解两个常用选项的使用方法。

    1)     “-I dir”  

    在GCC中使用头文件在默认情况下是在主程序中include所设定的标准路径,“<>”表示在标准路径中搜索头文件,在Linux中默认为“/usr/include”。但是头文件往往不是在标准路径下,所以就牵扯到了搜索路径的问题。那么如果想要改变该路径,你可以使用“-I dir”选项。“-I dir”选项可以在头文件的搜索路径列表中添加dir目录。这时,GCC就会到相应的位置查找对应的目录。下面是一个示例程序:

    假如你的main.c文件在/root/workplace/下:

    Main.c:

    #include <my.h>

    int main(int argc, char** argv)

    {

            printf("Hello!! ");

            return 0;

    }

    假如你想要包含的头文件my.h在“/root/workplace/gcc”下:

    my.h:

    #include <stdio.h>

    这样,头文件并不在当前程序编译的目录,这时你就可以在GCC命令行中加入“-I dir”选项,其命令如下所示:

    [root@localhost gcc]# gcc hello.c –I /root/workplace/gcc/ -o hello  // 编译

    2)    “-L dir”

    选项“-L dir”的功能与“-I dir”类似,其区别就在于“-L”选项是用于指明库文件的路径。例如有程序hello_sq.c需要用到目录“/root/workplace/gcc/lib”下的一个动态库libsunq.so,则只需键入如下命令即可:

    [root@localhost gcc]# gcc hello_sq.c –L /root/workplace/gcc/lib –lsunq –o hello_sq

    注意:

    l          注意引用共享库时的写法” –lsunq”,绿色标记的是小些的”L”。

    l          ‘-I dir’‘-L dir’都只是指定了路径,而没有指定文件,因此不能在路径中包含文件名。

  • 相关阅读:
    当前网页调用其他网页
    保护自己的网页不被放入框架
    保护网页源码
    页面的后退、刷新、前进
    妙味——拖拽+碰撞+重力
    运行代码
    妙味——弹性运动
    IE css bug及解决方案参考
    妙味——布局转换的应用
    [LeetCode][JavaScript]Count Complete Tree Nodes
  • 原文地址:https://www.cnblogs.com/davy2013/p/3157704.html
Copyright © 2020-2023  润新知