专栏首页Pou光明Linux共享库控制导出函数

Linux共享库控制导出函数

点击上方蓝字可直接关注!方便下次阅读。如果对你有帮助,麻烦点个在看或点个赞,感谢~ 文章首发 公众号—— 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"))) 将函数对外隐藏

本文分享自微信公众号 - Pou光明(pou0230),作者:PouG

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-10-19

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Linux不同共享库中同名函数的处理

    在一个尚未成熟的行业中,一般行业标准是先于国家标准。这就导致了开发人员需要做很多兼容工作,再就是会用到很多其他厂商提供的库与头文件,面对不同版本的标准,一般会更...

    用户5908113
  • 动态链接的相关结构

    在了解了共享对象的绝对地址的引用问题后,我们基本上对动态链接的原理有了初步的了解,接下来的问题是整个动态链接具体的实现过程了。动态链接在不同的系统上有不同的实现...

    233333
  • 【Linux程序设计】之Linux库函数的使用,多文件程序开发,静态与共享函数

    这个系列的博客贴的都是我大二的时候学习Linux系统高级编程时的一些实验程序,都挺简单的。贴出来纯粹是聊胜于无。

    马三小伙儿
  • Linux共享库、静态库、动态库详解

    使用GNU的工具我们如何在Linux下创建自己的程序函数库?一个“程序函数库”简单的说就是一个文件包含了一些编译好的代码和数据,这些编译好的代码...

    sunsky
  • 如何进行Linux平台共享库替换

    *本文原创作者:gaearrow,本文属FreeBuf原创奖励计划,未经许可禁止转载 。 共享库基础知识 程序由源代码变成可执行文件,一般可以分解为四个步骤...

    FB客服
  • 由一道面试题来了解进程间的通信

    周末面试碰到一个面试题,题目是: 在MMO游戏中,服务器采用Linux操作系统,网络通信与游戏逻辑处理进程一般是分离的。 例如:GameSvr进程处理游戏逻辑,...

    hbbliyong
  • sqlite3 多线程问题..

    这几天在做 学生考试系统,其中需要存储数据时要并发,然而我采用的sqlite3,小型数据库,导致了很多问题,特别是在多进程访问写的时候,特此分享给大家;

    py3study
  • 线程(一)线程概念+线程控制

    pthread_t 到底是什么类型呢?取决于实现。对于Linux目前实现的NPTL实现而言,pthread_t类型的线程ID,本质就是一个进程地址空间上的一个地...

    海盗船长
  • 动态链接的步骤与实现

    我们知道动态链接器本身也是一个共享对象,但是事实上它有一些特殊性。对于普通共享对象文件来说,它的重定位工作由动态链接器来完成。他也可以依赖其他共享对象,其中的被...

    233333
  • Linux漏洞分析入门笔记-栈溢出

    1. 在进行远程调试之前需要对Linux平台进行一些准备工作。在IDA的安装目录中的dbgsrv文件夹中,选择linux_server或者linux_serve...

    我是小三
  • 吴章金: 如何创建一个*可执行*的共享库

    license: "cc-by-nc-nd-4.0" description: "本文手把手指导如何创建一个可以执行的共享目标文件"

    Linux阅码场
  • 如何实现Android系统一分为二?--系统分身

    如今Android应用市场上的双开软件越来越多,譬如平行空间,双开大师,这些双开软件使得用户在同一台手机设备上使用同时登录两个微信账号,同时玩一个游戏的两个账号...

    skylinelulu
  • Linux动态链接库.so文件的创建与使用

            使用GNU的工具我们如何在Linux下创建自己的程序函数库?一个“程序函数库”简单的说就是一个文件包含了一些编译好的代码和数据,这些编译好的代码...

    阳光岛主
  • Android跨进程通信IPC之1——Linux基础

    由于Android系统是基于Linux系统的,所以有必要简单的介绍下Linux的跨进程通信,对大家后续了解Android的跨进程通信是有帮助的,本篇的主要内容如...

    隔壁老李头
  • 浅谈Linux的动态链接库

    上一篇我们分析了Hello World是如何编译的,即使一个非常简单的程序,也需要依赖C标准库和系统库,链接其实就是把其他第三方库和自己源代码生成的二进制目标文...

    PP鲁
  • Ubuntu 文件系统的概括

    1.根目录   根目录,即整个文件系统的逻辑终点,用“/”表示 2.一级目录   */bin 包含普通用户和系统、系统管理...

    静谧的小码农
  • 玩转「Wi-Fi」系列之wpa_supplicant 目录介绍(八)

    之后的文章基本都是wpa_supplicant源码分析的介绍, wpa_supplicant 一个庞大的开源项目, 最新版本的为2016-10-V2.6。据目前...

    程序手艺人
  • 深度解密Android中基于plt/got的hook实现原理

    我们日常开发中编写的C/C++代码经过NDK进行编译和链接之后,生成的动态链接库或可执行文件都是ELF格式的,它也是Linux的主要可执行文件格式。我们今天就要...

    open
  • Android 中的 Dalvik Heap 和 Native Heap

    Android系统对 dalvik 的 vm heapsize 作了硬性限制,当 java 进程申请的 java 空间超过阈值时,就会抛出OOM异常,可以通过a...

    王浩

扫码关注云+社区

领取腾讯云代金券