Linux下__attribute__((visibility ("default")))的使用

来源:互联网 发布:linux spoof 编辑:程序博客网 时间:2024/05/16 11:51

在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 __cplusplusextern "C" {#endifFBC_API_PUBLIC int library_add(int a, int b);FBC_API_LOCAL void print_log();#ifdef FBC_EXPORTFBC_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}")# 递归查询所有匹配的文件:*.cppFILE(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_LibraryADD_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






阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 2019芝麻分600分秒批1到5万 分镜头稿本 动画分镜头稿本 动画分镜头稿 4分管直径 6分管直径 6分管 分管 四分管 四分管直径 6分管外径 4分管 六分管 2分管是多大 4分管价格 净水器2分管 六分管的直径 六分管直径多少厘米 6分管是不是25管 4分管直径是20还是25 2分管直径是多少mm 4分管螺纹尺寸 6分管是20还是25 2分管等于多少mm 分管领导讲话稿 6分管是25还是20 6分管的直径是多少 1分管直径是多少 四分管是25还是20 一分管直径是多少毫米 4分管直径是多少 分管机空调是什么 1分管等于多少mm 3分管直径是多少 6分管的外径是多少 清朝九大总督分管图 分米 分米单位 分米厘米 分米和厘米 一分米