Chinaunix首页 | 论坛 | 博客
  • 博客访问: 357029
  • 博文数量: 132
  • 博客积分: 3066
  • 博客等级: 中校
  • 技术积分: 781
  • 用 户 组: 普通用户
  • 注册时间: 2009-04-14 16:19
文章分类

全部博文(132)

文章存档

2012年(1)

2010年(50)

2009年(81)

我的朋友

分类: C/C++

2010-05-18 16:20:57

这两天要做一个linux动态链接库.so文件,开始我选择用C++编写linux动态链接库,但在调用该链接库运行时会提示symbol找不到,如果用 C语言编写动态链接库运行时就可以得到正确的结果。开始还以为创建linux动态链接库so文件不能用c++,后来终于找到答案,使用C++时要使用 extern "C"。

使用linux动态链接库:
     在Unix上存在两种库:动态库(.so)和静态库(.a),采用动态库(共享对象)技术可以方便程序间共享,节省程序占有空间,增加程序的可扩展性和灵活性。
    操作动态库的函数在dlfcn.h文件中定义,所以要在使用动态库时include
   1. 打开动态链接库:dlopen,函数原型void *dlopen (const char *filename, int flag); dlopen用于打开指定名字(filename)的动态链接库,并返回操作句柄。比如,void *pHandle = dlopen(strSoFilePath, RTLD_LAZY);
   2. 取动态对象地址:dlsym,函数原型为: void *dlsym(void *handle, char *symbol); dlsym根据动态链接库操作句柄(handle)与符号(symbol),返回符号对应的地址。注意使用这个函数不但获取函数地址,也可以获取变量地址。比如,假设我在so中定义了一个void mytest()函数,那在使用so时先申明一个函数指针:void (*pMytest)();然后使用dlsym函数将函数指针pMytest指向mytest函数,pMytest = (void (*)())dlsym(pHandle, "mytest");
   3. 关闭动态链接库:dlclose,函数原型为: int dlclose (void *handle); 该函数将该.so的引用计数减一,当引用计数为0时,将它从系统中卸载。
   4. 动态库错误函数:dlerror,函数原型为: const char *dlerror(void); 当动态链接库操作函数执行失败时,dlerror可以返回出错信息,返回值为NULL时表示没有错误信息。
   在取到函数执行地址后,就可以在动态库的使用程序里面根据动态库提供的函数接口声明调用动态库里面的函数。在编写调用动态库的程序的makefile文件时,需要加入编译选项-ldl。

创建linux动态链接库:
    从void *dlsym(void *handle, char *symbol); 的参数可以看出,该函数只传两个参数:一个指向so的handle和一个函数的symbol,所以so里面的函数应该不允许重载,否则根据一个 symbol不能确定指向那个函数。为了兼容C和C++在so中定义函数时用extern "C",以下用例子说明如何创建linux动态链接库so文件。
C代码
  1. //test.h  
  2. #ifdef __cplusplus  
  3. extern "C"  
  4. {  
  5. #endif  
  6. void mytest();  
  7. #ifdef __cplusplus  
  8. }  
  9. #endif  
  10.   
  11. //test.c  
  12. #include   
  13. #include "mytest.h"  
  14. void mytest()  
  15. {  
  16.  printf("mytest ok in .so file\n");  
  17. }  
  18.   
  19. //main.cpp  
  20. #include   
  21. #include   
  22. //#include "mytest.h"  
  23.   
  24. void (*pMytest)();  
  25. bool testso()  
  26. {  
  27.  int errno = -1;  
  28.  char *error = NULL;  
  29.  const char *strSoFilePath = "./mytest.so";  
  30.  void *pHandle = dlopen(strSoFilePath, RTLD_LAZY);  
  31.  if( pHandle==NULL )  
  32.  {  
  33.   if( (error=dlerror())!=NULL )  
  34.   {  
  35.    printf("dlopen %s error, errno: %d, error info: %s\n", strSoFilePath, errno, error);  
  36.    return false;  
  37.   }  
  38.   else  
  39.   {  
  40.    printf("dlopen %s error, errno: %d\n",  strSoFilePath, errno);  
  41.    return false;  
  42.   }  
  43.  }  
  44.   
  45.  pMytest = (void (*)())dlsym(pHandle, "mytest");  
  46.  if( (error=dlerror()) != NULL )  
  47.  {  
  48.   printf("Can't get function Initialize: %s\n", error);  
  49.   return false;  
  50.  }  
  51.  pMytest();  
  52.  if( pHandle != NULL )  
  53.   dlclose(pHandle);  
  54.  return true;  
  55. }  
  56.   
  57. int main()  
  58. {  
  59.  if( testso() )  
  60.   printf("test so ok");  
  61.  else  
  62.   printf("test so fail");  
  63.   
  64.  return 0;  
  65. }  


Shell代码
  1. //Makefile  
  2. all : mytest.so testso  
  3.   
  4. .cpp.o :  
  5.  g++ -c -g -Wno-deprecated $(CFLAGS) $<  
  6.   
  7. .c.o :  
  8.  gcc -c -g -shared $(CFLAGS) $<  
  9.    
  10. mytest.so : mytest.o  
  11.  g++ mytest.o -g -shared -o mytest.so  
  12.    
  13. testso : main.o  
  14.  g++ main.o -rdynamic -s -g -Wl -o testso -ldl  
  15.    
  16. clean :  
  17.  rm -f *.o *.so testso  

 
阅读(1784) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~