我正在开发一个iOS应用程序,它链接了几个静态库。挑战在于,那些链接的库用不同的实现定义了相同的方法名。奇怪的是,我没有得到任何duplicate symbol definition
错误;但是,不出所料,我最终只能访问该方法的一个实现。
当我链接libA和libB,并调用func1()时,它解析为libA或libB的实现而没有任何编译警告。但是,我需要能够分别访问libA的func1()和libB的func1()。
有一个类似的SO帖子解释了如何在C中完成(通过符号重命名),但不幸的是,正如我发现的那样,objcopy
工具不适用于ARM架构(因此iPhone)。
(我将提交它到App Store,因此,动态链接不是一个选项)
看来你很幸运-你仍然可以用ARM二进制格式重命名符号,它只是比objcopy
方法更黑客…
还请注意,这只适用于未使用c++编译器编译的文件!如果在这些文件上使用c++编译器,这个将失败。
- 首先,你需要一个像样的十六进制编辑器,对于这个例子,我将使用hex恶魔。
接下来,您将打开一个库的副本,我们将其命名为
lib1-renamed.a
,并对其执行以下操作:找到要重命名的符号的名称。它可以使用
nm
工具找到,或者,如果你知道头名称,你应该设置。接下来,您将使用十六进制,并以文本替换旧名称(在本例中为
foo
),并给它一个新名称(在本例中为bar
)。这些名称必须具有相同的长度,否则会破坏二进制的偏移量!注意:如果有多个函数包含
foo
的名字,你可能会有问题
现在,您必须编辑您更改的库的头文件,以使用新的函数名(
bar
)而不是旧的函数名。
如果你已经正确地完成了上面三个简单的†步骤,你现在应该能够编译&成功链接两个文件,并调用两个实现。
如果您试图使用通用二进制文件(例如,在模拟器上也是如此),您最好使用lipo
来分离两个二进制文件,在i386/x64二进制文件上使用objcopy
,然后在ARM二进制文件上使用我的方法,并将lipo
重新组合在一起。
†:不保证简单性,也不包括在Richard J. Ross III超级保修范围内。想了解更多关于超级保修的信息,请拨打1-800-FREE-WARRANTY。现在是1-800免费保修!