C/C++程序隐藏符号
使用visibility
#if defined _WIN32 || defined __CYGWIN__ #ifdef MY_NO_EXPORT #define API #else #define API __declspec(dllexport) #endif #else #ifdef __GNUC__ #define API __attribute__((visibility("default"))) #else #define API #endif #endif #if defined __cplusplus #define EXTERN extern "C" #else #include <stdarg.h> #include <stdbool.h> #define EXTERN extern #endif #define MY_API EXTERN API
GNU C 的一大特色就是attribute 机制。
试想这样的情景,程序调用某函数A,A函数存在于两个动态链接库liba.so,libb.so中,并且程序执行需要链接这两个库,此时程序调用的A函数到底是来自于a还是b呢?
这取决于链接时的顺序,比如先链接liba.so,这时候通过liba.so的导出符号表就可以找到函数A的定义,并加入到符号表中,链接libb.so的时候,符号表中已经存在函数A,就不会再更新符号表,所以调用的始终是liba.so中的A函数。
为了避免这种混乱,所以使用
__attribute__((visibility("default"))) //默认,设置为:default之后就可以让外面的类看见了。 __attribute__((visibility("hideen"))) //隐藏
设置这个属性。
visibility
用于设置动态链接库中函数的可见性,将变量或函数设置为hidden
,则该符号仅在本so中可见,在其他库中则不可见。
g++在编译时,可用参数-fvisibility
指定所有符号的可见性(不加此参数时默认外部可见,参考man g++中-fvisibility部分);若需要对特定函数的可见性进行设置,需在代码中使用attribute设置visibility属性。
编写大型程序时,可用-fvisibility=hidden
设置符号默认隐藏,针对特定变量和函数,在代码中使用attribute ((visibility("default")))
另该符号外部可见,这种方法可用有效避免so之间的符号冲突。
经在代码中测试,
C++的extern __attribute__((visibility("default")))
会导出函数参数,
C的extern "C" __attribute__((visibility("default")))
的方式不会导出函数参数,两者不能通用。
使用version-script
set_target_properties(your_so_or_exe PROPERTIES LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/symbol.version")
symbol.version:
{ global:JNI_OnLoad;JNI_OnUnload;Java_*;usedFun; local:*; };
我最擅长从零开始创造世界,所以从来不怕失败,它最多也就让我一无所有。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!