zoukankan      html  css  js  c++  java
  • Linux动态库应用

    Linux动态库应用

    简介:

    • 动态库在编程过程中是一个很重要的技术,在实际开发过程中,我们在设计各模块时,常常会用到一些通用的功能,如文件处理,网络接口等。这时候,我们可以有两种选择:一种是用动态链接技术,一种是静态链接技术。动态链接,顾名思义,就是在程序运行时调用动态库中的函数。静态链接,则是在编译时就已经把代码拷贝到程序中。相比来说,动态库更节省空间与资源,但静态库调用速度更快,因为它是直接编译进程序中;静态库还有一个缺点是当一个静态库被修改时,整个涉及的模块都要重新编译,这对软件更新还说是一个很大的问题,而动态库则只需要更新库文件就可以完成更新。

    动态库调用方式一

    1. 库函数介绍:
      函数原型说明备注
      void *dlopen(const char *filename, int flag) 该函数将打开一个新库,并把它装入内存 头文件:dlfcn.h,编译时需加上-ldl参数(gcc/g++)
      char *dlerror(void) 库函数报错函数
      void *dlsym(void *handle, const char *symbol) 获取库符号的地址
      void *dlclose(void *handle) 关闭库与dlopen对应
    2. 设计一个动态库libfunc.so
      1 /****************************func.c***********************************/
      2 #include <stdio.h>
      3 
      4 void func()
      5 {
      6     printf("this is call func");
      7 }
      1 /****************************func.h***********************************/
      2 
      3 #ifdef __FUNC_H__
      4 #define __FUNC_H__
      5 
      6 void func(void);
      7 
      8 #endif
      
      
    3. 用如下命令生成一个动态链接库: 
      1 linux@skytrails$ gcc -shared -fPIC -o libfunc.so func.c
    4. 设计调用libfunc.so的主函数:
       1 /****************************main.c***********************************/
       2 #include <dlfcn.h>
       3 #include <stdlib.h>
       4 #include <stdio.h>
       5 #include "func.h"
       6 int main() {
       7     void * handle;
       8     void (*pfunc)(void);
       9     char *error;
      10     handle = dlopen("libfunc.so", RTLD_NOW);
      11     if (NULL == handle){
      12         printf("call dlopen failed!");
      13         exit(0);
      14     }
      15     pfunc = (void(*)(void))dlsym(handle, "func");
      16     if (NULL == pfunc){
      17         error = dlerror();
      18         printf("call dlsym failed!%s", error);
      19     }
      20     else{
      21         (*pfunc)();
      22     }
      23     printf("
      ");
      24     pfunc = (void(*)(void))dlsym(handle, "func1");
      25     if (NULL == pfunc){
      26         error = dlerror();
      27         printf("call dlsym failed!%s
      ", error);
      28     }
      29     else{
      30         (*pfunc)();
      31     }
      32     printf("
      ");
      33     pfunc = (void(*)(void))dlsym(handle, "func2");
      34     if (NULL == pfunc){
      35         error = dlerror();
      36         printf("call dlsym failed!%s
      ", error);
      37     }
      38     else{
      39         (*pfunc)();
      40     }
      41     printf("
      ");
      42     pfunc = (void(*)(void))dlsym(handle, "func3");
      43     if (NULL == pfunc){
      44         error = dlerror();
      45         printf("call dlsym failed!%s
      ", error);
      46     }
      47     else{
      48         (*pfunc)();
      49     }
      50     printf("
      ");
      51     pfunc = (void(*)(void))dlsym(handle, "func4");
      52     if (NULL == pfunc){
      53         error = dlerror();
      54         printf("call dlsym failed!%s
      ", error);
      55     }
      56     else{
      57         (*pfunc)();
      58     }
      59     printf("
      ");
      60     exit(1);
      61 }
    5. 链接libfunc.so生成可执行文件:
      1     linux@skytrails$ gcc -shared -fPIC main.c -o main -ldl
    6. 在命令行下运行可得到:
      1     linux@skytrail$ ./main
      2     call dlsym failed!./libfunc.so: undefined symbol: func
      3     this is call func1
      4     this is call func2
      5     this is call func3
      6     this is call func4
    7. 完整的编译可以制作成简易的makefile文件:
      1 ################################ makefile文件 ################################
      2 all:libfunc.so main
      3 libfunc.so:func.c func.h
      4     gcc $< -o libfunc.so -fPIC -shared
      5 main:main.c
      6     gcc $< -o main -ldl
    8. 注意事项:
      • 调用库函数dlopen,dlsym,dlclose时要加载库libdl.so。
      • linux为程序动态库提供了5种搜索的路径,系统默认不搜索当前目录,可以根据下文的动态库搜索路径自已选择一种方式,否则找不到指定库文件。
      • 如果把func.c文件后缀改成.cpp,则会以c++方式编译,这时会调用dlsym失败,提示找不到func*符号。这里因为c/c++的差异,需要在函数名前指定为extern "c"。
    • 动态库搜索路径
      优先级路径备注
      1 DT_RPATH(ELF可执行文件中动态段) 编译目标代码时,对编译器(gcc/g++)加入链接参数-Wl,-rpath指定动态库搜索路径。优先级最高
      2 LD_LIBRARY_PATH Linux环境变量
      3 /etc/ld.so.conf中指定动态库路径 不同Linux系统文件不一样(debain)。这里是debain系统
      4 /lib 默认动态为搜索路径
      5 /usr/lib

    动态库调用方式二

    1. 简介:
      • 第二种方式其实前面已经应用了。就是libdl.so的调用,在调用库函数dlopen等时需要用到。下面用一个代码实例来说明其应用。
    2. 代码示例(libfunc.so库复用上面代码,makefile与main.c作一点小小的修改即可):
       1 /******************************* main.c ******************************/
       2 #include <stdlib.h>
       3 #include <stdio.h>
       4 #include "func.h"
       5 int main() {
       6     func1();
       7     printf("
      ");
       8     func2();
       9     printf("
      ");
      10     func3();
      11     printf("
      ");
      12     func4();
      13     printf("
      ");
      14     exit(1);
      15 }
      1 ################################ makefile文件 ################################
      2 all:libfunc.so main
      3 libfunc.so:func.c func.h
      4     gcc $< -o libfunc.so -fPIC -shared
      5 main:main.c
      6     gcc $< -o $@ -L. -lfunc
    3. 执行make
      1 linux@skytrails$ make
      2 gcc func.c -o libfunc.so -fPIC -shared
      3 gcc main.c -o main -L. -lfunc
    4. 执行程序
      1 linux@skytrails$ ./main
      2 this is call func1
      3 this is call func2
      4 this is call func3
      5 this is call func4
    ..... created by skytrails
  • 相关阅读:
    Something I know about WebDynpro
    Details about support package implementation
    CRM Middleware Performance Topics
    Way to configure the logon navigaion layouts via Business Roles in CRM
    DOM 常用节点类型和方法
    第一届 xdef 会议日程
    去除百度音乐盒广告的chrome插件 持续更新
    从人人网抓取高校数据信息,包括,省份 高校 院系 (提供最终SQL文件下载)
    PHP 与 JSON
    解决HTTPS 发送请求走socket问题
  • 原文地址:https://www.cnblogs.com/skytrails/p/4865531.html
Copyright © 2011-2022 走看看