Chinaunix首页 | 论坛 | 博客
  • 博客访问: 9463849
  • 博文数量: 1750
  • 博客积分: 12961
  • 博客等级: 上将
  • 技术积分: 20091
  • 用 户 组: 普通用户
  • 注册时间: 2009-01-09 11:25
个人简介

偷得浮生半桶水(半日闲), 好记性不如抄下来(烂笔头). 信息爆炸的时代, 学习是一项持续的工作.

文章分类

全部博文(1750)

文章存档

2024年(26)

2023年(26)

2022年(112)

2021年(217)

2020年(157)

2019年(192)

2018年(81)

2017年(78)

2016年(70)

2015年(52)

2014年(40)

2013年(51)

2012年(85)

2011年(45)

2010年(231)

2009年(287)

分类: 其他平台

2017-02-10 10:39:22


GCC的符号可见性——解决多个库同名符号冲突问题  -- 很好的文章



1. 把符号表中的函数变成LOCAL的呢,最直接的就是加上visibility为hidden的标志,即把重名函数上加入  __attribute__ ((visibility ("hidden"))) 即可,则说明本函数只有对本库内的函数有用。库内函数调用时也会自动调用库内的同名函数。Makefile用原有固定方式即可。

    2. windows平台对于符号的行为是不一样的,windows默认动态库里符号是LOCAL的,通过__declspec(dllexport)来声明GLOBAL符号。
    3. 
最安全的方式为: 做动态库SO时,把内部函数声明为__attribute__ ((visibility ("hidden")))即可,这样不必区分函数时在同个文件内还是分散在多个文件中。



1. 动态库B/C 里边或者 调用者 host A 都存在同名函数,且需要统一使用的A函数实现时,linux的默认就是host A的同名函数会覆盖库中的函数。而库B要调用A的某些函数时需要 -export-dynamic选项。
1.1 要在库中导出某些特定函数时可以用(函数前加入 __attribute ((visibility("default"))) ,编译时加入 -fvisibility=hidden,前提是同名函数和导出函数在同个文件内)。例如

点击(此处)折叠或打开

  1. /******************************** lib_1.c **************************************/
  2. #include <stdio.h>
  3. #include <stdlib.h>

  4. void foo(void)
  5. {
  6.     fprintf(stderr, "lib_1 foo.\n");
  7. }

  8. __attribute ((visibility("default")))
  9. void bar_1()
  10. {
  11.     foo();
  12. }



  13. /********************************lib_2.c***********************/
  14. #include <stdio.h>
  15. #include <stdlib.h>

  16. void foo(void)
  17. {
  18.     fprintf(stderr, "lib_2 foo.\n");
  19. }

  20. __attribute ((visibility("default")))
  21. void bar_2()
  22. {
  23.     foo();
  24. }


  25. /***************** main.c *******************************/
  26. void foo(void)
  27. {
  28.     fprintf(stderr, "main foo.\n");
  29. }

  30. void bar_main()
  31. {
  32.     foo();
  33. }

  34. int main()
  35. {

  36.     bar_1();
  37.     bar_2();
  38.     bar_main();
  39.     return 0;
  40. }

  41. /***********************编译*************************/
  42. rm *.so
  43. rm *.o
  44. rm test
  45. sudo rm -rf /usr/local/lib/libtest_*.so

  46. gcc -fPIC -fvisibility=hidden -c -o lib_1.o lib_1.c
  47. gcc -fPIC -fvisibility=hidden -c -o lib_2.o lib_2.c

  48. gcc -shared -o libtest_1.so lib_1.o -fvisibility=hidden
  49. gcc -shared -o libtest_2.so lib_2.o -fvisibility=hidden

  50. gcc -c -o main.o main.c
  51. gcc -o test main.o -L. -ltest_1 -ltest_2
  52. sudo cp libtest_1.so libtest_2.so /usr/local/lib/ -f
  53. sudo ldconfig

  54. /*******************************运行结果***************************/
  55. lib_1 foo.
  56. lib_2 foo.
  57. main foo.
但当lib_1.c 中 foo函数和 bar_1 在不同的 C 文件中时, 结果则会发生变化,此时只能用动态加载库的方式。如下。

2. 动态库B/C 里边或者 调用者 host A 都存在同名函数,且每个库都需要自己内部的的函数实现时,需要用动态调用的方式加载。如下

点击(此处)折叠或打开

  1. /********************** lib_1.c  ***************************************/
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4.  
  5. void bar_1()
  6. {
  7.     foo();
  8. }

  1. /********************** lib_1_ext.c  ***************************************/
  1. #include <stdio.h>
  2. #include <stdlib.h>

  3. void foo(void)
  4. {
  5.     fprintf(stderr, "lib_1 foo.\n");
  6. }

  1. /********************** lib_2.c  ***************************************/
  1. #include <stdio.h>
  2. #include <stdlib.h>

  3. void bar_2()
  4. {
  5.     foo();
  6. }

  1. /********************** lib_2_ext.c  ***************************************/
  1. #include <stdio.h>
  2. #include <stdlib.h>

  3. void foo(void)
  4. {
  5.     fprintf(stderr, "lib_2 foo.\n");
  6. }


  7. /********************** main.c  ***************************************/
  8. #include <stdlib.h>
  9. #include <stdio.h>
  10. #include <stdint.h>
  11. #include <string.h>
  12. #include <unistd.h>
  13. #include <dlfcn.h>

  14. void foo(void)
  15. {
  16.     fprintf(stderr, "main foo.\n");
  17. }

  18. void bar_main()
  19. {
  20.     foo();
  21. }

  22. int main()
  23. {
  24.     void *handler_1, *handler_2;
  25.     void (*hdr_bar_1)(void);
  26.     void (*hdr_bar_2)(void);
  27.     handler_1 = dlopen("./libtest_1.so", RTLD_LAZY);
  28.     handler_2 = dlopen("./libtest_2.so", RTLD_LAZY);
  29.     *(void **)&hdr_bar_1 = dlsym(handler_1, "bar_1");
  30.     *(void **)&hdr_bar_2 = dlsym(handler_2, "bar_2");
  31.     if (!hdr_bar_1 || !hdr_bar_2)
  32.     {
  33.         fprintf(stderr, "not bar_x func found.\n");
  34.         return -1;
  35.     }

  36.     hdr_bar_1();
  37.     hdr_bar_2();

  38.     bar_main();
  39.     return 0;
  40. }

  41. /********************** 编译  ***************************************/
  42. rm test
  43. gcc -fPIC -c -o lib_1.o lib_1.c
  44. gcc -fPIC -c -o lib_2.o lib_2.c
  45. gcc -fPIC -c -o lib_1_ext.o lib_1_ext.c
  46. gcc -fPIC -c -o lib_2_ext.o lib_2_ext.c

  47. gcc -shared -o libtest_1.so lib_1.o lib_1_ext.o
  48. gcc -shared -o libtest_2.so lib_2.o lib_2_ext.o

  49. gcc -c -o main.o main.c
  50. gcc -o test main.o -ldl

/********************** 运行结果  ***************************************/

lib_1 foo.
lib_2 foo.
main foo.

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