点击上方蓝字可直接关注!方便下次阅读。如果对你有帮助,麻烦点个在看或点个赞,感谢~ 文章首发 公众号—— Pou光明
在上海出差辛勤工作的第三天......
之前的文章介绍了Linux中对共享库中同名函数的处理规则——根据链接库的顺序来确定调用哪个函数。
本次介绍共享库其他一些有意思的性质。
在我们开发过程中,难免会使用到第三方库,而且时不时还需要更新,某些情况下还要兼容不同版本并维护。
按照上次验证的结果,如果两个不同版本库中有同名函数,并且需要兼容,那我们如何确定要调用哪个函数呢?使用链接库的顺序来处理,显然不是一个好办法。【虽然大部分情况下库的函数名称都是不一样的】
再来一个场景,当我们拿到第三方库和头文件,我们还想看下库里面还有哪些其他的函数接口,这时可以使用 nm -D *.so 进行查看。下面以libone.so为例说明,红线部分为我自己定义的函数。
为了解耦函数,会将功能模块拆解成多个函数,但实际暴露给用户的时候可能只有几个。如果想让用户使用nm -D *.so命令查看时只看到封装的几个函数,在编写makefile时可以使用CFLAGS += -fvisibility=hidden 标志,再将给用户的函数名称前加上__attribute__((visibility("default")))即可。
makefile使用CFLAGS += -fvisibility=hidden标志时,会将所有函数全部隐藏,不使用该标志时,默认所有函数全部公开。
gcc 版本4以上可用【未测试】。
测试用例源码:
1. Create shareLib
libOne.h
#ifndef __LIBONE_API_H__
#define __LIBONE_API_H__
#define OPEN_API_DEFAULT __attribute__((visibility("default")))
#define OPEN_API_HIDDEN __attribute__((visibility("hidden")))
// #define OPEN_API_LIBONETEST
#ifdef __cplusplus
extern "C"
{
#endif
/*
*名称:测试用例
*描述:
*参数:无
*返回值:0————成功;其他————错误号。
*说明:
*/
OPEN_API_DEFAULT int myPrintfDefault();
OPEN_API_HIDDEN int myPrintfHidden();
#ifdef __cplusplus
}
#endif
#endif
libOne.c
#include "libOne.h"
#include <stdio.h>
#define OPEN_API_LIBONETEST_DEFAULT __attribute__((visibility("default")))
#define OPEN_API_LIBONETEST_HIDDEN __attribute__((visibility("hidden")))
// #define OPEN_API_LIBONETEST_SRC
OPEN_API_LIBONETEST_DEFAULT int myPrintfDefault()
{
printf("Hi , I am is lib One default ! \n");
return 0;
}
OPEN_API_LIBONETEST_HIDDEN int myPrintfHidden()
{
printf("Hi , I am is lib One hidden ! \n");
return 0;
}
Makefile :
#################################################################
# PRIVATE PART #
#################################################################
APP_STACK_DIR = .
# 内部头文件
INC_CFLAGS += -I $(APP_STACK_DIR)/Inc
# 对外接口目录
#INC_CFLAGS += -I $(APP_STACK_DIR)/Intf
# 动态链接库
#LDFLAGS += -lName -lName
# 源文件
CSRC += $(APP_STACK_DIR)/Src/*.c
C_OBJS += $(patsubst %.c,%.o,$(wildcard $(CSRC)))
# 动态库编译标志
DEBUG = y
ifeq ($(DEBUG),y)
DEBUG_CFLAGS += -DDEBUG
DEBUG_CFLAGS += -g
endif
CFLAGS += -c
CFLAGS += -Os
CFLAGS += -Wall
CFLAGS += -fPIC
CFLAGS += -fvisibility=hidden #隐藏属性
CFLAGS += $(DEBUG_CFLAGS)
# 目标文件
#Target_Lib=$(APP_STACK_DIR)./appTest/libOne.a
Target_Dll=$(APP_STACK_DIR)./appTest/lib/libone.so
TARGET = $(Target_Lib) $(Target_Dll)
# 编译规则
all:$(TARGET)
$(Target_Lib):$(C_OBJS)
$(AR) rcs $@ $^
@echo -e "\n>>>>> Compiling *$(Target_Lib)* sucessfully ended\n"
$(Target_Dll):$(C_OBJS)
$(CC) -shared $^ -o $@
@echo -e "\n>>>>> Compiling *$(Target_Dll)* sucessfully ended\n"
$(C_OBJS):%.o:%.c
$(CC) $(CFLAGS) $(INC_CFLAGS) $< -o $@
.PHONY:all clean
clean:
-rm -f $(C_OBJS)
-rm -f $(TARGET)
2. Test Code
如需完成测试工程代码,可在Pou光明公众号后台留言。
3. __attribute__((visibility("hidden"))) 将函数对外隐藏