骚操作:利用强弱符号制作插件库

当有强符号和弱符号时,选择使用强符号

那么我们正可以利用这个原则做以下事情:

  • 定义为弱符号,如果是弱符号,使用默认行为

  • 如果链接了库,是强符号,则使用外部定义行为

以此来实现一个类似插件的功能。通俗一点说:

  • 当没有插件时,使用默认行为

  • 链接了插件时,使用插件的功能

原理和示例

其原理也非常简单:

  • 外部引用弱符号

  • 如果符号地址为0,则说明外部没有链接插件库,未有强符号,走默认流程

  • 如果符号地址不为0,则说明链接了插件库,执行插件库的功能。

示例程序如下:

#include
__attribute__((weak)) void my_print();void test_print()
{// 如果是强符号,说明链接了外部插件,使用外部定义if(my_print){my_print();}else{// 弱符号,走默认逻辑printf("this is weak print\n");}
}
int main(void)
{test_print();return 0;
}

上面的test_print函数是弱符号,在没有其他地方定义的情况下,也是能够正常编译运行的:

$ gcc -o main main.c
$ ./main
this is weak print

观察可执行文件:

$ nm main |grep my_printw my_print

通过nm命令我们也可以知道test_print是弱符号,它前面的修饰字符是W,代表weak。

插件库

前面的示例程序已经能否工作了,如何让它能否支持插件库呢?或者说,如何让它支持外部的插件功能呢?

这里以静态库为例:

// print_plugin.c
#include
void my_print()
{printf("this is plugin print\n");
}

制作静态库:

$ gcc -c print_plugin.c
$ ar -rcs libprint_plugin.a print_plugin.o

链接插件库

现在重新编译main程序,并使用插件库:

$ gcc -o main main.c -L./ -lprint_plugin
$ gcc  -o main  main.c  -L. -Wl,--whole-archive -lprint_plugin -Wl,--no-whole-archive
$ nm main |grep my_print
000000000000067a T my_print
$ ./main
this is plugin print

需要注意的是,这里在链接插件库之前,需要加上:

-Wl,--whole-archive

该选项会将插件库中所有符号都链接进来,若非如此,在main.c中已经有了my_print符号,将不会链接进来,而在此之后,又要将该选项恢复。最终我们可以通过nm命令看到my_print符号已经不再是W了。也就看到了最后:

this is plugin print

的打印了。

也就实现了我们所谓插件的功能,换句话说,可以对目标程序进行功能的裁剪或者增加。

总结

由于以下几点原因,我们可以自己做一些支持插件库的程序:

  • 1.重复强弱符号同存在时,使用强符号

  • 2.弱符号链接不存在时,不会报错

  • 3.未链接的外部符号,地址为0,可通过判断避免访问非法地址

再结合前面的例子分别解释一下:

1.在开始的程序中,即便没有链接插件库,程序也可以正常编译链接通过,而不会报错
2.没有链接插件库时,由于其函数地址为0,因此,我们程序内判断,if(xxx),当地址为0时,执行默认的行为语句。

声明:

本文于网络整理,版权归原作者所有,如来源信息有误或侵犯权益,请联系我们删除或授权事宜。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/338643.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c语言里 t是什么作用,c语言里的\t是什么意思

c语言里的\t是什么意思以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!c语言里的\t是什么意思正宗叫法是“水平制表符”,就是在输出媒体上水平跳过多个空格…

boot jersey_Jersey和Spring Boot入门

boot jersey除了许多新功能,Spring Boot 1.2还带来了Jersey支持。 这是吸引喜欢标准方法的开发人员的重要一步,因为他们现在可以使用JAX-RS规范构建RESTful API,并将其轻松部署到Tomcat或任何其他Springs Boot支持的容器中。 带有Spring平台的…

mime类型是什么 node_Node.js - 文件系统获取文件类型

我需要借助node.js来获取文件的文件类型以设置内容类型。我知道我可以很容易地检查文件扩展名,但我也有没有扩展名的文件,其内容类型应该是image/png,text/html aso。Node.js - 文件系统获取文件类型这是我的代码(我知道这并没有太大的意义,但…

函数或全局变量重复定义时会怎样?

可能有些朋友第一反应是,那肯定是编译不过喽:// fun.c #include void func() {printf("编程珠玑\n"); }// main.c #include void func() {printf("公众号\n"); } int main(void) {func();return 0; }编译:$ gcc -o main …

c语言开源编辑器,一个C语言编写的跨平台C语言编译器(开源) UCC

很多科班出身的搞开发的同事大都应该学过《编译原理》这门课程,或许也动手做过一些实践。这次向大家推荐一个由清华大学学生完成的C语言编译器实现 -- UCC。这个项目目前位于sf.net网站,开放源代码,代码使用C语言编写,对于理解和实…

java持久性与安全性_Java持久性锁定初学者指南

java持久性与安全性隐式锁定 在并发理论中,锁定用于保护可变共享数据免受危险数据完整性异常的影响。 因为锁管理是一个非常复杂的问题,所以大多数应用程序都依赖于其数据提供程序隐式锁技术。 将整个锁定职责委托给数据库系统既可以简化应用程序开发&a…

c语言实验报告5数组,c语言实验报告五一维数组.doc

c语言实验报告五一维数组《C程序设计》课程实验报告学院: 班级: 姓名: 学号: 实验设备:计算机1台2011年3月1日实验项目名称一维数组掌握一维数组的定义、初始化,以及一维数组元素的下标法引用。实验要求&am…

当C语言函数执行成功时,返回1和返回0究竟哪个好?

基本上,没有人会将大段的C语言代码全部塞入 main() 函数。更好的做法是按照复用率高,耦合性低的原则,尽可能的将代码拆分不同的功能模块,并封装成函数。C语言代码的组合千变万化,因此函数的功能可能会比较复杂&#xf…

ubuntu自定义安装里怎么选_超市里的五香粉怎么选?看懂配料表,两个小技巧,不怕选不好。...

点击右上角【关注】,可获得本头条号推荐的更多美食干货五香粉是家庭常用的一种调味料,焖、炖、烧、煮、卤都常备使用,如今市场上的五香粉品牌也是相当繁多,质量也是参差不齐,有时买到的五香粉烧制的菜肴根本就不好吃&a…

原来C语言还可以这样实现“泛型编程”!

在回答标题问题之前,先了解下什么是泛型编程。泛型编程(generic programming)是程序设计语言的一种风格或范式。泛型允许程序员在强类型程序设计语言中编写代码时使用一些以后才指定的类型,在实例化时作为参数指明这些类型。C支持…

javadoc 标签_新的Javadoc标签@ apiNote,@ implSpec和@implNote

javadoc 标签如果您已经在使用Java 8,则可能会看到一些新的Javadoc标签: apiNote , implSpec和implNote 。 他们怎么了? 如果要使用它们,该怎么办? 总览 该帖子将快速查看标签的来源和当前状态。 然后&…

c语言万年历附加功能,万年历(c语言,多功能).doc

万年历(c语言,多功能)#include "time.h" /*包含的头文件*/#include "stdio.h"#include "math.h"#include "windows.h"#include "conio.h"#define KEYNUMUp 0x48 /*宏定义*/#define KEYNUMDown 0x50#define KEYNUMLeft 0x4b#…

联想小新300加固态_就联想小新 Pro 13 固态硬盘混用一事,官方回应

IT之家11月3日消息 近日有用户反馈称,联想小新Pro 13的部分批次固态硬盘从三星PM981A换成亿联了,因此还出现了退货现象。针对上述情况,联想官方刚刚发表声明回应此事。以下为联想回应全文:有关小新Pro 13固态硬盘(SSD)配置问题的公…

C语言入门基础之输入和输出

标准输入函数在stdio.h中scanf声明如下:/* Read formatted input from stdin.This function is a possible cancellation point and therefore notmarked with __THROW. */ extern int scanf (const char *__restrict __format, ...) __wur;使用Mac或Linux的同学&am…

camel java_与Java EE和Camel的轻量级集成

camel javaEnterprise Java具有不同的风格和观点。 从简单的平台技术(众所周知的Java EE)开始,到不同的框架和集成方面,最后是涉及以数据为中心的用户界面或特定可视化效果的用例。 Java EE本身无法解决的最突出的问题是“集成”。…

c语言 伪随机数程序,C语言的伪随机数

一直想好好的系统的学习一下C语言的伪随机数,今天终于逮到机会了伪随机数C语言中有可以产生随机数据的函数,需要添加stdlib.h和time.h头文件。首先在main函数开头加上srand(unsigned)time(NULL))。先来介绍一下srand头文件:定义函数&#xff…

最大隶属度原则_模糊数学笔记:六、模糊模型识别-I(最大隶属度原则)

1、模型识别的问题提出模型识别,通俗地理解即是对一个类别未知的对象进行归类(或者叫分类)。这里与聚类不同的是,聚类实际上是要区分出已有的样本哪些属于同一类,但并没有参考标准。而识别则事先有参考的标准&#xff…

C语言经典题

C 库函数 - tanh()描述C 库函数 double tanh(double x) 返回 x 的双曲正切。声明下面是 tanh() 函数的声明。double tanh(double x)参数x -- 浮点值。返回值该函数返回 x 的双曲正切。实例下面的实例演示了 tanh() 函数的用法。#include#include int main (){ double x, ret;…

用c语言产生大素数,C语言实现寻找大素数

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼找到一亿内所有素数并写入文件用时 35秒.#include "math.h"#include "stdio.h" #include "stdlib.h" #include "time.h"int isP(int num,int *p) { int i; int lenp[0]; int flag1; p;for…

java ee自动生成编码_EE Servlet 3:在Servlet中生成HTML输出

java ee自动生成编码如果您只需要在EE Web模块中处理少量请求URI,那么在Servlet代码中生成自己HTML响应可能比使用完整的模板库更容易。 作为示例的一部分,我尝试了一个非常简单的Java DSL,该Java DSL在编写自己的Serlvet时生成html输出。 代…