专题1库的使用

    技术2022-05-20  45

    1.库概述

    库可以分为静态库和动态库,静态库编译时必须存在,程序运行时不需要。动态库也称共享库,其代码不会链接到目标文件之中,只有当动态库可访问时,应用程序才能正确地执行动态库函数。执行动态库有两种方式:隐式调用和显示调用。隐式调用也称共享库的静态加载,动态库函数在应用程序开始执行时会自动载入内存,进程结束时又自动卸载。编译方式与静态库一致。显示调用也称共享库的动态加载,调用时必须遵守dlopen等函数的规则实现调用。

     

    Unix中,使用ar命令可以创建或操作静态库,其格式为:

    ar [drqtpmx] [option] archivefile objfile ….

    参数

    意义

    -r

    objfile文件插入静态库尾或替换静态库中同名文件

    -x

    从静态库文件中抽取文件objfile

    -t

    打印静态库的成员文件列表

    -d

    从静态库文件中删除文件objfile

    -s

    重置静态库文件索引

    -v

    创建文件冗余信息

    -c

    创建静态库文件

     

    例子:抽取静态库/usr/lib/lic.a中的文件

    # ar –x /usr/lib/libc.a

    例子:组织文件xcvt.oxstat.o创建静态库libccc.a

    # ar –r libccc.a xcvt.o xstat.o

     

    2. 静态库编程

    2.1 设计库源码

    /******pr1.c*****/

    void pirnt1()

    {

           printf(“this is the first lib src/n”);

    }

    /*******pr2.c***********/

    void print2()

    {

           printf(“this is the second lib src/n”);

    }

     

    2.2. 编译生成库文件

    gcc –O –c pr1.c pr2.c

    分别产生pr1.o, pr2.o文件

    链接静态库

    ar –rsv libpr.a pr1.o pr2.o

    创建库文件后,可以创建库的索引来帮助提高必须和库连接的其他程序的编译速度。使用ranlib程序创建库的索引。索引存放在库文件内部。

    ranlib     libpr.a

    可以使用nm程序显示存档文件的索引。nm程序用于显示目标文件的符号。

    nm –s lib pr.a | more

    2.3 测试程序源码

    /********main.c************/

    int main()

    {

           print1();

           print2();

    }

    2.4 编译运行

    gcc –O –o main main.c –L./ -lpr

     

    3. 动态库编程

    3.1 库源码

    /*******pr1.c********/

    int p=2;

    void print()

    {

           printf(“This is the first dll src!/n”);

    }

    /*******pr2.c*********/

    int p = 3;

    void print()

    {

           printf(“This is the second dll src!/n”);

    }

     

    3.2 编译生成动态库

    gcc –O –fpic –shared –o d1.so pr1.c

    gcc –O –fpic –shared –o d2.so pr2.c

    动态加载器必须知道如何访问共享库dl.sodl.so。有两种方式:一是利用LD_LIBRARY_PATH环境变量。二是利用/etc/ld.so.conf文件。命令ldd可以查看一个可执行程序所依赖的库,将当前动态库所在的目录加入到环境变量LD_LIBRARY_PATH后,系统就可以根据此变量查找到所需要的库。另外,也可以将库的路径添加到/etc/ld.so.conf文件中,然后使用命令ldconfig,更新文件ld.so.cache,动态加载器将使用它来查找所需的库。

    3.3. 动态库的隐式调用

    /*****main.c*****/

    int main()

    {

           print();

    }

    cp d1.so dll.so cp d2.so dll.so

    编译:gcc –O –o main main.c ./dll.so

     

    3.4. 动态库的显式调用

    #include <dlfcn.h>

    int main()

    {

            void *pHandle;//动态库句柄

            void (*pFunc)();//函数指针

            int *p;

            pHandle = dlopen("./dll.so", RTLD_NOW);

            if(!pHandle)

            {

                    printf("Cann't find dll.so/n");

                    return 1;

            }

    /*

     *     *(void**)(&pFunc ) = dlsym(pHandle, "print");

    *      (*pFunc)();

    */

            pFunc = (void(*)())dlsym(pHandle, "print");

            if(pFunc)

            {

                    pFunc();

            }

            else

            {

                    printf("Can't find func print/n");

            }

     

            p = (int *)dlsym(pHandle, "p");

            if(p)

            {

                    printf("p=%d/n", *p);

            }

            else

            {

                    printf("Can't find int p/n");

            }

            dlclose(pHandle);

     

            return 0;

    }

     


    最新回复(0)