我在从 C 源代码创建的两个库 libA.a(静态)和 libB.so(动态)之间存在链接问题。
在用于生成 libB.so 的源文件之一中,我有以下功能:
static uint64_t unassigned_mem_read(void *opaque, hwaddr addr, unsigned size) { ... }
static void unassigned_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { ... }
当我运行 nm libB.so | grep unassigned_mem
我有:
00000000004662a7 t unassigned_mem_read
0000000000466337 t unassigned_mem_write
在用于制作 libA.a 的源文件中,我有:
extern uint64_t unassigned_mem_read(void *opaque, hwaddr addr, unsigned size);
extern void unassigned_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size);
再进一步调用这些方法。
当我编译时,一切正常。但是在链接处,我有:
[build] qmg-mmio.c:47: undefined reference to 'unassigned_mem_read'
[build] qmg-mmio.c:84: undefined reference to 'unassigned_mem_write'
当我执行 nm libA.a | 时grep unassigned_mem
我有:
U unassigned_mem_read
U unassigned_mem_write
我按以下顺序链接:libB.so、libA.a。
既然符号是一样的,为什么不能解析呢?
此外,当我将所有源代码编译在一起时,我的链接就没有问题了。将静态库和动态库完全链接在一起时是否存在我想念的微妙之处?
最佳答案
对于文件范围标识符,static
关键字指定内部链接。这意味着标识符和任何关联的定义对于它们出现的翻译单元来说基本上是私有(private)的。为了避免混淆,请注意这仅与“静态库”外围相关,尤其是静态库中打算由库用户直接调用的函数必须不声明static
,因为它直接且明确地阻止了此类调用。
链接是标识符的属性,在它们的范围内,不是它们标识的对象或函数的属性,也不一定是其他范围内的相同标识符的属性。此外,同一标识符可以与不同范围内的不同对象和/或函数相关联。特别是,给定标识符的 extern
al 声明与不同的函数或对象相关联,而不是与相同标识符的任何内部声明相关联的函数或对象,因此您不能将出现在一个范围内的内部声明重新定义为通过在其他范围内添加声明来实现外部范围。
由于您似乎不愿意修改包含您要调用的函数的库,我假设它是由第三方提供的。在那种情况下,您应该明白,将这些函数声明为 static
的部分目的是为了让库用户您不要调用他们直接。它们不是图书馆外部接口(interface)的一部分。
关于c - 使用 extern 关键字的链接出现 undefined reference 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54371594/