从C源代码创建的两个库libA.a(静态)和libB.so(动态)之间的链接时出现问题。
在用于生成libB.so的源文件之一中,我具有以下功能:
$(jqID).off('click');
$(jqID).on('click', function(){deSelect(this.id, 1)});
运行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
在用于制作libA.a的源文件中,我得到了:
00000000004662a7 t unassigned_mem_read
0000000000466337 t unassigned_mem_write
还有一些这些方法被称为。
编译时,一切正常。但是在链接上,我有:
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
我按以下顺序链接:libB.so,libA.a。
由于符号相同,是什么使它们不被解析?
此外,当我将所有源代码一起编译时,链接没有问题。完全链接我想念的静态库和动态库时是否存在子技巧?
答案 0 :(得分:3)
对于文件作用域标识符,static
关键字指定内部链接。这意味着标识符和任何关联的定义对于出现它们的翻译单元基本上是私有的。为避免混淆,请注意,这仅与“静态库”有关,尤其是静态库中打算由库用户直接调用的函数必须不声明{{ 1}},因为它可以直接阻止此类调用。
链接是标识符的属性,在它们的范围内,而不是它们标识的对象或函数,在其他范围内不一定是同一标识符。此外,同一标识符可以与不同范围内的不同对象和/或功能相关联。特别是,给定标识符的static
al声明与不同于同一个标识符的任何内部声明的函数或对象相关联,因此您不能将在一个作用域中出现的内部声明重新定义为外部函数或对象。通过在其他范围内添加声明。
由于您似乎不愿意修改包含要调用的函数的库,因此我假设它是由第三方提供的。在这种情况下,您应该了解声明这些功能extern
的部分目的是使库用户 you 不要直接调用它们。它们不是库的外部接口的一部分。