Chinaunix首页 | 论坛 | 博客
  • 博客访问: 24498
  • 博文数量: 10
  • 博客积分: 27
  • 博客等级: 民兵
  • 技术积分: 60
  • 用 户 组: 普通用户
  • 注册时间: 2011-07-14 13:31
文章分类
文章存档

2012年(10)

我的朋友
最近访客

分类:

2012-07-23 11:41:06

平时我们在开发的过程,常常将某些模块编译成共享库,以方便大家使用。
而我常用的方法,使用共享库提供的API,然后将其和自己的代码一起编译。
如果共享库进行的更改,我们则需要重新编译,这样不便宜程序更新。
然而linux 提供dlopen  dlsym 等API 允许我们在运行时动态加载和链接共享库
这样一来共享库如有更新,只需在相应的目录下更新共享库而不用重新编译程序
这样就非常方便程序的后续升级了

下面是一个简单的试例:

debug.h

点击(此处)折叠或打开

  1. #ifndef __DEBUG_H__
  2. #define __DEBUG_H__

  3. #define DEBUG 1

  4. #ifdef DEBUG
  5. #include <stdio.h>
  6. #include <stdarg.h>

  7. #define DebugWhere() \
  8.     printf("FILE:%s,FUNC:%s,LINE:%d\n",\
  9.             __FILE__,__FUNCTION__,__LINE__)

  10. static inline void debug_p(const char *format,...)
  11. {
  12.     va_list args;

  13.     va_start(args,format);
  14.     vprintf(format,args);
  15.     va_end(args);
  16. }
  17. #else

  18. #define DebugWhere()

  19. static inline void debug_p(const char *format,...)
  20. {}

  21. #endif

  22. #endif
share_lib.c

点击(此处)折叠或打开

  1. #include
  2. #include
  3. #include
  4. #include "debug.h"

  5. int accumulation(int n,...)
  6. {
  7. int i = 0;
  8. int result = 0;
  9. va_list args;

  10. DebugWhere();
  11. va_start(args,n);
  12. for (i=0; i
  13. result += va_arg(args,int);
  14. }
  15. va_end(args);
  16. debug_p("result is:%d\n",result);

  17. return result;
  18. }

  19. #if 0
  20. int main()
  21. {
  22. printf("20 + 10 =%d\n",accumulation(2,20,10));

  23. return 0;
  24. }
  25. #endif
编译写共享库:

点击(此处)折叠或打开

  1. gcc -shared -fPIC share_lib.c -o share.so

test.c

点击(此处)折叠或打开

  1. /* Copyright(C) 2012 for free
  2.  * All right reserved
  3.  */
  4. /**
  5.  * @file load_dynamical_lib.c
  6.  * @synopsis 运行时动态加载和链接共享库 测试例程
  7.  * @author sense, linuxboy2008@gmail.com
  8.  * @version 1.0
  9.  * @date 2012-07-20
  10.  */
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <dlfcn.h>
  14. #include <assert.h>

  15. typedef int TBOOL;
  16. #define FALSE ((int) 0)
  17. #define TRUE ((int)1)

  18. /* --------------------------------------------------------------------------*/
  19. /**
  20.  * @synopsis open_library 加载和链接共享库
  21.  *
  22.  * @param libname 要加载和链接的共享库
  23.  *
  24.  * @returns 打开的的句柄
  25.  */
  26. /* --------------------------------------------------------------------------*/
  27. void *open_library(char *libname)
  28. {
  29.     void *lib;

  30.     lib = dlopen(libname,RTLD_LOCAL | RTLD_LAZY);
  31.     if (lib == NULL){
  32.         fprintf(stderr,"%s:failed to open:%s:%s\n",__FUNCTION__,libname,dlerror());
  33.         return NULL;
  34.     }

  35.     return lib;
  36. }

  37. /* --------------------------------------------------------------------------*/
  38. /**
  39.  * @synopsis get_library_symbol 获取共享库中指定符号的地址
  40.  *
  41.  * @param lib 打开的共享库的句柄
  42.  * @param func_name 要获取的符号名
  43.  *
  44.  * @returns 获取到的符号的地址
  45.  */
  46. /* --------------------------------------------------------------------------*/
  47. void *get_library_symbol(void *lib,const char *func_name)
  48. {
  49.     void *symbol;

  50.     symbol = dlsym(lib,func_name);
  51.     if (symbol == NULL){
  52.         fprintf(stderr,"%s:failed to get symbol:%s:%s\n",__FUNCTION__,func_name,dlerror());
  53.         return NULL;
  54.     }

  55.     return symbol;
  56. }


  57. /* --------------------------------------------------------------------------*/
  58. /**
  59.  * @synopsis close_library 卸载共享库
  60.  *
  61.  * @param lib    打开的共享库的句柄
  62.  *
  63.  * @returns 0:失败 1:成功
  64.  */
  65. /* --------------------------------------------------------------------------*/
  66. TBOOL close_library(void *lib)
  67. {
  68.     int status;
  69.     
  70.     assert(lib != NULL);

  71.     status = dlclose(lib);
  72.     if (status < 0)
  73.     {
  74.         fprintf(stderr,"%s:failed to close:%s\n",__FUNCTION__,dlerror());
  75.         return FALSE;
  76.     }

  77.     return TRUE;
  78. }

  79. int main(int argc,char *argv[])
  80. {
  81.     char *libname = "./share.so";
  82.     void *lib = NULL;
  83.     int ret = 0;
  84.     int (*add)(int ,...); //和共享库中的API相同,函数同可相同也可不相同

  85.     lib = open_library(libname);
  86.     add = get_library_symbol(lib,"accumulation"); //共享库中的函数名
  87.     ret = add(2,10,20);
  88.     printf("test.c: %d\n",ret);
  89.     printf("test.c: %d\n",add(3,10,20,30));

  90.     ret = close_library(lib);

  91.     return ret;
  92. }
Makefile:

点击(此处)折叠或打开

  1. CC=gcc

  2. CFLAGS=-rdynamic -O2
  3. TARGET=test
  4. SRC=test.c

  5. all:
  6.     ${CC} ${CFLAGS} -o ${TARGET} ${SRC} -ldl
  7. clean:
  8.     rm *.o ${TARGET}

测试:
# ./test
FILE:share_lib.c,FUNC:accumulation,LINE:12
result is:30
test.c: 30
FILE:share_lib.c,FUNC:accumulation,LINE:12
result is:60
test.c: 60

参考:
《深入理解计算机 》 链接  章节

稍作修改:

点击(此处)折叠或打开

  1. /* Copyright(C) 2012 for free
  2.  * All right reserved
  3.  */
  4. /**
  5.  * @file load_dynamical_lib.c
  6.  * @synopsis 运行时动态加载和链接共享库 测试例程
  7.  * @author sense, linuxboy2008@gmail.com
  8.  * @version 1.0.1
  9.  * @date 2012-07-24
  10.  */
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <dlfcn.h>

  14. typedef int (*FUNC)(int ,...); //和共享库中的API相同,函数同可相同也可不相同
  15. typedef int TBOOL;
  16. #define FALSE ((int) 0)
  17. #define TRUE ((int)1)

  18. /* --------------------------------------------------------------------------*/
  19. /**
  20.  * @synopsis open_library 加载和链接共享库
  21.  *
  22.  * @param libname 要加载和链接的共享库
  23.  *
  24.  * @returns 打开的的句柄
  25.  */
  26. /* --------------------------------------------------------------------------*/
  27. void *open_library(char *libname)
  28. {
  29.     void *lib;

  30.     lib = dlopen(libname,RTLD_LOCAL | RTLD_LAZY);
  31.     if (lib == NULL){
  32.         fprintf(stderr,"%s:failed to open:%s:%s\n",__FUNCTION__,libname,dlerror());
  33.         return NULL;
  34.     }

  35.     return lib;
  36. }

  37. /* --------------------------------------------------------------------------*/
  38. /**
  39.  * @synopsis get_library_symbol 获取共享库中指定符号的地址
  40.  *
  41.  * @param lib 打开的共享库的句柄
  42.  * @param func_name 要获取的符号名
  43.  *
  44.  * @returns 获取到的符号的地址
  45.  */
  46. /* --------------------------------------------------------------------------*/
  47. void *get_library_symbol(void *lib,const char *func_name)
  48. {
  49.     void *symbol;

  50.     symbol = dlsym(lib,func_name);
  51.     if (symbol == NULL){
  52.         fprintf(stderr,"%s:failed to get symbol:%s:%s\n",__FUNCTION__,func_name,dlerror());
  53.         return NULL;
  54.     }

  55.     return symbol;
  56. }


  57. /* --------------------------------------------------------------------------*/
  58. /**
  59.  * @synopsis close_library 卸载共享库
  60.  *
  61.  * @param lib    打开的共享库的句柄
  62.  *
  63.  * @returns 0:失败 1:成功
  64.  */
  65. /* --------------------------------------------------------------------------*/
  66. TBOOL close_library(void *lib)
  67. {
  68.     int status;
  69.     
  70.     if (lib != NULL)
  71.         return FALSE;

  72.     status = dlclose(lib);
  73.     if (status < 0)
  74.     {
  75.         fprintf(stderr,"%s:failed to close:%s\n",__FUNCTION__,dlerror());
  76.         return FALSE;
  77.     }

  78.     return TRUE;
  79. }

  80. int main(int argc,char *argv[])
  81. {
  82.     char *libname = "./share.so";
  83.     void *lib = NULL;
  84.     int ret = 0;
  85.     FUNC add;

  86.     lib = open_library(libname);
  87.     add = get_library_symbol(lib,"accumulation"); //共享库中的函数名
  88.     ret = add(2,10,20);
  89.     printf("test.c: %d\n",ret);
  90.     printf("test.c: %d\n",add(3,10,20,30));

  91.     ret = close_library(lib);

  92.     return ret;
  93. }
阅读(947) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~