Linux共享库的输出符号表

我们在看很多第三方库的源码时,会发现这些库的实现代码,都会在对外暴露的接口前面加上一个宏,类似这种形式:

1
2
3
Q_EXPORT class A {
...
};

这就是在指定class A是暴露出来的接口。接下来介绍具体如何定义。

通过gcc编译共享库时,默认所有的类和函数是全局可见的,也就是代码种所有的类和函数都会生成符号表,别人再用的时候能链接到所有的类和函数。

gcc有一个编译选项 -fvisibility=hidden,他的作用是隐藏所有的类和函数,配合着宏定义使用,能实现暴露指定的接口。

通常的用法是这样:

  • 在代码中进行如下定义,定义了一个宏Q_EXPORT:
1
2
3
#if !defined(Q_EXPORT)
#define Q_EXPORT __attribute__((visibility("default")))
#endif
  • 在需要暴露的接口前面加上这个宏:

    1
    2
    3
    Q_EXPORT class A {
    ...
    };
  • 在编译选项中再加入 -fvisibility=hidden

通过以上三步,代码中有Q_EXPORT宏的地方就是对外暴露的(default就是public),其余地方就被隐藏。其原理就是通过编译选项-fvisibility=hidden指定所有接口都隐藏,但是代码中有attribute((visibility(“default”)))的地方单独暴露出来。

以上是Linux下的处理方式,Windows平台的宏定义是另外一种方式,所有通常跨平台的代码要先判断平台,再根据不同平台定义Q_EXPORT.

有一个工具 nm 可以查看共享库暴露的符号表。

参考:https://blog.csdn.net/ld11690/article/details/81227480