在Linux下动态库(.so)中,通过GCC的C++ visibility属性可以控制共享文件导出符号。在GCC 4.0及以上版本中,有个visibility属性,可见属性可以应用到函数、变量、模板以及C++类。

限制符号可见性的原因:从动态库中尽可能少地输出符号是一个好的实践经验。输出一个受限制的符号会提高程序的模块性,并隐藏实现的细节。动态库装载和识别的符号越少,程序启动和运行的速度就越快。导出所有符号会减慢程序速度,并耗用大量内存。

“default”:用它定义的符号将被导出,动态库中的函数默认是可见的。”hidden”:用它定义的符号将不被导出,并且不能从其它对象进行使用,动态库中的函数是被隐藏的。default意味着该方法对其它模块是可见的。而hidden表示该方法符号不会被放到动态符号表里,所以其它模块(可执行文件或者动态库)不可以通过符号表访问该方法。

要定义GNU属性,需要包含__attribute__和用括号括住的内容。可以将符号的可见性指定为visibility(“hidden”),这将不允许它们在库中被导出,但是可以在源文件之间共享。实际上,隐藏的符号将不会出现在动态符号表中,但是还被留在符号表中用于静态链接

导出列表由编译器在创建共享库的时候自动生成,也可以由开发人员手工编写。导出列表的原理是显式地告诉编译器可以通过外部文件从对象文件导出的符号是哪些。GNU用户将此类外部文件称作为”导出映射”。

以下是测试代码,各个文件的内容如下:

Dynamic_Library/library.hpp:

#ifndef FBC_LIBRARY_LIBRARY_HPP_
#define FBC_LIBRARY_LIBRARY_HPP_// reference: https://gcc.gnu.org/wiki/Visibility
//            https://developer.apple.com/library/content/documentation/DeveloperTools/Conceptual/CppRuntimeEnv/Articles/SymbolVisibility.html#ifdef __GNUC__ >= 4 // it means the compiler is GCC version 4.0 or later#ifdef FBC_EXPORT#warning "===== dynamic library ====="#define FBC_API_PUBLIC __attribute__((visibility ("default")))#define FBC_API_LOCAL __attribute__((visibility("hidden")))#else#warning "===== static library ====="#define FBC_API_PUBLIC#define FBC_API_LOCAL#endif
#else#error "##### requires gcc version >= 4.0 #####"
#endif#ifdef __cplusplus
extern "C" {
#endifFBC_API_PUBLIC int library_add(int a, int b);
FBC_API_LOCAL void print_log();#ifdef FBC_EXPORT
FBC_API_PUBLIC int value;
#endif#ifdef __cplusplus
}
#endiftemplate<typename T>
class FBC_API_PUBLIC Simple {
public:Simple() = default;void Init(T a, T b);T Add() const;private:T a, b;
};#endif // FBC_LIBRARY_LIBRARY_HPP_

Dynamic_Library/library.cpp:

#include "library.hpp"
#include <iostream>
#include <string>FBC_API_PUBLIC int library_add(int a, int b)
{
#ifdef FBC_EXPORTvalue = 11;
#endiffprintf(stdout, "File: %s, Function: %s, Line: %d\n", __FILE__, __FUNCTION__, __LINE__);return (a+b);
}FBC_API_LOCAL void print_log()
{fprintf(stderr, "print_log function is hidden, in dynamic library: %s, %d\n", __FUNCTION__, __LINE__);
}template<typename T>
void Simple<T>::Init(T a, T b)
{this->a = a;this->b = b;
}template<typename T>
T Simple<T>::Add() const
{fprintf(stdout, "File: %s, Function: %s, Line: %d\n", __FILE__, __FUNCTION__, __LINE__);return (a + b);
}template class Simple<int>;
template class Simple<std::string>;

Test_Dynamic_Library/test_library.hpp:

#ifndef FBC_CPPBASE_TEST_TEST_LIBRARY_HPP_
#define FBC_CPPBASE_TEST_TEST_LIBRARY_HPP_namespace test_library_ {#ifdef __cplusplusextern "C" {
#endifint test_library_1();
int test_library_2();
int test_library_3();#ifdef __cplusplus}
#endif} // namespace test_library_#endif // FBC_CPPBASE_TEST_TEST_LIBRARY_HPP_

Test_Dynamic_Library/test_library.cpp:

#include "test_library.hpp"
#include <iostream>
#include <string>#include <library.hpp>namespace test_library_ {int test_library_1()
{int a{ 4 }, b{ 5 }, c{ 0 };c = library_add(a, b);fprintf(stdout, "%d + %d = %d\n", a, b, c);#ifdef FBC_EXPORTfprintf(stdout, "dynamic library: value: %d\n", value);
#endifreturn 0;
}int test_library_2()
{Simple<int> simple1;int a{ 4 }, b{ 5 }, c{ 0 };simple1.Init(a, b);c = simple1.Add();fprintf(stdout, "%d + %d = %d\n", a, b, c);Simple<std::string> simple2;std::string str1{ "csdn blog: " }, str2{ "http://blog.csdn.net/fengbingchun" }, str3;simple2.Init(str1, str2);str3 = simple2.Add();fprintf(stdout, "contents: %s\n", str3.c_str());return 0;
}int test_library_3()
{
#ifdef FBC_EXPORTfprintf(stdout, "dynamic library cann't run print_log function\n");
#elseprint_log();
#endifreturn 0;
}} // namespace test_library_

Test_Dynamic_Library/main.cpp:

#include <iostream>
#include "test_library.hpp"int main()
{test_library_::test_library_1();test_library_::test_library_2();test_library_::test_library_3();return 0;
}

CMakeLists.txt:

# CMake file for Samples_Dynamic_Library# 设定依赖的CMake版本
CMAKE_MINIMUM_REQUIRED(VERSION 3.2)# 指定项目名称
PROJECT(Test_Dynamic_Library)# 打印相关信息, CMAKE_CURRENT_SOURCE_DIR指的是当前处理的CMakeLists.txt所在的路径
MESSAGE(STATUS "current path: ${CMAKE_CURRENT_SOURCE_DIR}")# 使CMake支持C++11特性
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu++0x")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++0x")# 定义用户自定义变量
SET(PATH_DYNAMIC_LIBRARY_CPP_FILES ${CMAKE_CURRENT_SOURCE_DIR}/Dynamic_Library)
SET(PATH_TEST_DYNAMIC_LIBRARY_CPP_FILES ${CMAKE_CURRENT_SOURCE_DIR}/Test_Dynamic_Library)
SET(PATH_DYNAMIC_LIBRARY_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Dynamic_Library)
#MESSAGE(STATUS "Dynamic Library cpp files path: ${PATH_DYNAMIC_LIBRARY_CPP_FILES}")
#MESSAGE(STATUS "Test Dynamic Library cpp files path: ${PATH_TEST_DYNAMIC_LIBRARY_CPP_FILES}")# 递归查询所有匹配的文件:*.cpp
FILE(GLOB_RECURSE DYNAMIC_LIBRARY_CPP_LIST ${PATH_DYNAMIC_LIBRARY_CPP_FILES}/*.cpp)
FILE(GLOB_RECURSE TEST_DYNAMIC_LIBRARY_CPP_LIST ${PATH_TEST_DYNAMIC_LIBRARY_CPP_FILES}/*.cpp)
#MESSAGE(STATUS "Dynamic Library cpp list: ${DYNAMIC_LIBRARY_CPP_LIST}")
#MESSAGE(STATUS "Test Dynamic Library cpp list: ${TEST_DYNAMIC_LIBRARY_CPP_LIST}")IF (BUILD_DYNAMIC_LIBRARY)# 添加编译参数,添加-D预编译宏定义,可以一次添加多个ADD_DEFINITIONS(-DFBC_EXPORT)# 生成动态库ADD_LIBRARY(Dynamic_Library SHARED ${DYNAMIC_LIBRARY_CPP_LIST})
ELSE()ADD_LIBRARY(Static_Library STATIC ${DYNAMIC_LIBRARY_CPP_LIST})
ENDIF()# 指定需要包含的头文件
INCLUDE_DIRECTORIES(${PATH_DYNAMIC_LIBRARY_INCLUDE_DIR})# 生成可执行文件Test_Dynamic_Library
ADD_EXECUTABLE(Test_Dynamic_Library ${TEST_DYNAMIC_LIBRARY_CPP_LIST})
IF (BUILD_DYNAMIC_LIBRARY)# 用来为target添加需要链接的共享库,指定工程所用的依赖库,包括动态库和静态库TARGET_LINK_LIBRARIES(Test_Dynamic_Library Dynamic_Library)
ELSE()TARGET_LINK_LIBRARIES(Test_Dynamic_Library Static_Library)
ENDIF()

编译方法(ReadMe.txt):

在Linux下通过CMake编译Samples_Dynamic_Library中的测试代码步骤:
将终端定位到Linux_Code_Test/Samples_Dynamic_Library,依次执行如下命令:
$ mkdir build
$ cd build
// Note:-DBUILD_DYNAMIC_LIBRARY=1,编译生成动态库; -DBUILD_DYNAMIC_LIBRARY=0, 编译生成静态库
$ cmake -DBUILD_DYNAMIC_LIBRARY=1 ..
$ make (生成动态库和执行文件)
$ ./Test_Dynamic_Library

GitHub:https://github.com/fengbingchun/Linux_Code_Test

Linux下__attribute__((visibility (default)))的使用相关推荐

  1. C语言之__attribute__((visibility(“default“)))等gcc flag讲解(六十二)

    目录 1.概述 2.程序说明 <1>.test.h <2>.test.c <3>.main.c 3.编译实验 <1>.gcc显示声明:-fvisibil ...

  2. Linux下__attribute__((aligned(n)))的使用

    关键字__attribute__允许你在定义struct.union.变量等类型时指定特殊属性.此关键字后面是跟着双括号括起来的属性说明.__attribute__不属于标准C语言,它是GCC对C语言 ...

  3. __attribute__((visibility(default)))

    网址:http://blog.csdn.net/mutourenzhang/article/details/47803803 网址:http://www.cnblogs.com/fortunely/p ...

  4. linux怎么判断全局符号,Linux下全局符号覆盖有关问题

    Linux下全局符号覆盖问题 在windows上,默认情况下,动态库中的符号都是对外隐藏的,除非你显示的指出要导出哪些符号,否则外界是看不到的.但是linux下情况刚好相反,对静态变量和全局变量,li ...

  5. __attribute__((visibility()))

    Table of Contents __attribute__((visibility("default"))) 1. 当-fvisibility=hidden时 2. 当-fvi ...

  6. Linux下减小动态库大小的方法

    在一些业务场景下,需要对动态库的大小进行限制,主要有如下几种方法: 1. 编译选项使用-Os,表示以最小化大小为优化方向 2. 去除-g选项,进而去除调试信息 3. 通过strip裁剪符号及调试信息 ...

  7. Linux下locale: Cannot set LC_CTYPE to default locale: No such file or directory警告

    在Linux下使用locale命令提示如下警告: locale: Cannot set LC_CTYPE to default locale: No such file or directory lo ...

  8. Linux下的静态链接库和动态链接库编程

    Linux下的静态链接库和动态链接库编程 参考: Linux下的静态链接库和动态链接库编程 - Histring - 博客园 Mac下静态库和动态库的创建和使用_C/C++_vincent2610的专 ...

  9. 64位Slitaz Linux下Glibc 2.20编译式更新安装成功

    目录 一.编译需求 二.编译前的环境 三.编译的程序包 四.开始编译 五.总结 一.编译需求 我使用的是64位Slitaz的linux系统(中文),glibc的版本只有2.14.1,运行teamvie ...

最新文章

  1. 网易盖楼回复的简易实现
  2. 阿里云态势感知服务(上篇)
  3. 序列化类型 System.Data.Entity.DynamicProxies 的对象时检测到循环引用
  4. caffe学习(二):利用mnist数据集训练并进行手写数字识别(windows)
  5. Linux之解析鼠标input事件数据
  6. ubuntu下eclipse新建项目没有java project的解决办法
  7. 用选框工具画圆角矩形
  8. [功能发布]Excel催化剂地图可视化功能正式发布,欢迎使用!
  9. [密码学基础][每个信息安全博士生应该知道的52件事][Bristol Cryptography][第20篇]Merkle-Damgaard hash函数如何构造
  10. mysql java文件导入导出_MySQL文件导出和导入
  11. Dubbo源码分析笔记-一(工程目录介绍)
  12. 浅谈TCP优化(转)
  13. 关于VBScript的运行环境
  14. 20款免费公司企业wordpress主题
  15. android 字体适配_移动端postcss-pxtorem rem适配方案
  16. thinkphp学习简易教程(一) thinkphp创建项目
  17. 基于Python的微信公众号爬虫
  18. 利用接口(vue等)调用thinkphp6(tp6)验证码验证结果总是失败的解决方案
  19. 谢烟客-----Linux的发展史
  20. Python Day 67 Dango框架图解(总结)、Wsgiref和uwsgi、前后端传输数据的编码格式、From表单和Ajax方式在前端往后端发送文件、补充一下页面清缓存...

热门文章

  1. LabVIEW条形码识别(实战篇—5)
  2. 深度学习(5)感知机(神经元)与神经网络
  3. TensorFlow(1)TensorFlow基础(整体介绍)
  4. java8u211_jre864位u211
  5. 动态内存管理和智能指针 2.0 -- shared_ptr
  6. .net core在vs开发环境下脱离iis运行
  7. SQL SERVER的锁机制(三)——概述(锁与事务隔离级别)
  8. 7、在对象内部尽量直接访问实例变量
  9. 理解Python的迭代器(转)
  10. git review devops过程