原文连接:http://blog.gotocoding.com/archives/875
今天有同学提出,如何在一个C程序中让两个不同版本的库共存。
首先想到的方案是,把其中一个版本的库函数全部重命名,比如把每一个函数名都加一个_v2的后缀。
人工替换到没什么,但是如果函数个数超过10个,就有点不拿人当人使了。
而使有工具去替换就会遇到一些棘手的问题,如何识别哪些是函数,哪些是系统函数(系统函数不需要添加后缀)等。
随后想到的另一个解决方案是c++的方案,为其中一个版本库中的所有文件添加命名空间,然后使用g++将这部分代码编译成. o文件,之后再使用gcc将这些。阿文件与整个程序中的其他代码进行链接。
不过需要注意的是,g++编译后所有导出接口名都会变化得不那么直观。
考虑一个C语言的编译链接过程。
首先会将每个C文件编译成。阿文件。
在编译过程中,导出函数并不会被实际分配地址,而是将函数名以F符号的方式存在。阿文件的符号表中。
在本c文件调用的函数如果不存在于本文件,也会生成一个和的符号存在。阿文件的符号表中。
在链接过程中,链接器接收输入的. o文件,为每个。阿文件中的符号分存地址,并生成可执行文件。
有了这几点事实,问题就变得的简单多了。
首先将其中一个版本的库中所有代码编译为. o文件。然后收集所有。阿文件中F的符号。
由于整个库代码有内部依赖关系,收集到的F符号必然是所有。阿文件中和符号的超集。
换句话说,所有的F符号名就是我们要重命名的所有函数名。
这里我们需要借助objdump和objcopy工具.objdump - t用于列的表。阿文件的符号表,objcopy用于重命名符号。
我随手写了一段用于过虑F符号的lua脚本
12345678910111213 <代码类=" lua评论">——重命名。lua代码> <代码类=" lua关键词大胆">本地代码> <代码类=發ua平原”>列表={}代码> <代码类=" lua关键词大胆">本地代码> <代码类=發ua平原”> reg=代码> <代码类=" lua字符串"> " ([^ % s] +) % s + ([^ % s] +) % s + ([^ % s] +)" 代码> <代码类=發ua平原”> . .代码> <代码类=發ua空间”>,,,,,,,,代码> <代码类=" lua字符串"> " % s + ([^ % s] +) % s + ([^ % s] +) % s + ([^ % s] +)" 代码> <代码类=" lua关键词大胆">为代码> <代码类=發ua平原”> l 代码> <代码类=" lua关键词大胆">在代码> <代码类=" lua函数大胆"> io 代码> <代码类=發ua平原”> .stdin:线条()代码> <代码类=" lua关键词大胆"> 代码>做<代码类=發ua空间”>,,,,,,,,代码> <代码类=" lua关键词大胆">本地代码> <代码类=發ua平原”> a, b, c, d, e, f=代码> <代码类=" lua函数大胆">字符串代码> <代码类=" lua平原">。匹配(l, reg) 代码> <代码类=發ua空间”>,,,,,,,,代码> <代码类=" lua关键词大胆">如果代码> <代码类=發ua平原”> 代码> <代码类=" lua关键词大胆">和代码> <代码类=發ua平原”> c==代码> <代码类=發ua字符串”>“F”代码> <代码类=" lua关键词大胆">然后代码> <代码类=發ua空间”>,,,,,,,,,,,,,,,,代码> <代码类=發ua平原”>列表(#列表+ 1)=代码> <代码类=" lua字符串“>”——redefine-sym”代码> <代码类=發ua空间”>,,,,,,,,,,,,,,,,代码> <代码类=發ua平原”>列表(#列表+ 1)=代码> <代码类=" lua函数大胆">字符串代码> <代码类=" lua平原">。代码> <代码类=" lua函数大胆">格式代码> <代码类=發ua平原”>(代码> <代码类=發ua字符串”>“% s=% s_v2”代码> <代码类=發ua平原”>,f, f) 代码> <代码类=發ua空间”>,,,,,,,,代码> <代码类=" lua关键词大胆"> 代码>结束<代码类=" lua关键词大胆"> 代码>结束<代码类=" lua函数大胆">打印代码> <代码类=發ua平原”>(代码> <代码类=發ua字符串”>“#/bin/sh”代码> <代码类=" lua平原">)代码> <代码类=" lua函数大胆">打印代码> <代码类=發ua平原”>(代码> <代码类=發ua字符串”>“objcopy”代码> <代码类=發ua平原”> . .代码> <代码类=" lua函数大胆">表代码> <代码类=發ua平原”> .concat(列表). .代码> <代码类=發ua字符串”>“$ 1”代码> <代码类=" lua平原">)代码>我们可以使用如下命令来收集所有。阿文件的F符号,并产生修改符号所用的脚本1