17

Linux共享库控制导出函数

 3 years ago
source link: https://mp.weixin.qq.com/s?__biz=MzUxMTk4MzY3MA%3D%3D&%3Bmid=2247484629&%3Bidx=1&%3Bsn=1e91dff2199ca907cfbc248e191d6672
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

点击上方蓝字可直接关注!方便下次阅读。如果对你有帮助,麻烦点个在看或点个赞,感谢~          文章首发   公众号—— Pou光明

在上海出差辛勤工作的第三天......

之前的文章介绍了Linux中对共享库中同名函数的处理规则——根据链接库的顺序来确定调用哪个函数。

本次介绍共享库其他一些有意思的性质。

在我们开发过程中,难免会使用到第三方库,而且时不时还需要更新,某些情况下还要兼容不同版本并维护。

按照上次验证的结果,如果两个不同版本库中有同名函数,并且需要兼容,那我们如何确定要调用哪个函数呢?使用链接库的顺序来处理,显然不是一个好办法。【虽然大部分情况下库的函数名称都是不一样的】

再来一个场景,当我们拿到第三方库和头文件,我们还想看下库里面还有哪些其他的函数接口,这时可以使用 nm -D *.so 进行查看。下面以libone.so为例说明,红线部分为我自己定义的函数。

VnQZziM.png!mobile

为了解耦函数,会将功能模块拆解成多个函数,但实际暴露给用户的时候可能只有几个。如果想让用户使用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

rq6VZj6.png!mobile

如需完成测试工程代码,可在Pou光明公众号后台留言。

3.  __attribute__((visibility("hidden"))) 将函数对外隐藏

MZzeIjR.png!mobile

欢迎大家关注公众号—— Pou光明


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK