对直接从静态库创建的共享库中函数的未定义引用
undefined reference to function in shared library created directly from static library
我有一个包含简单模拟器的旧静态库。模拟器通过调用函数 (sim) 启动,该函数也包含在库中。现在,我想把这个静态库变成动态库:
g++ -shared -fPIC -o libdynamicSimulator.so -Wl,--whole-archive libstaticSimulator.a -Wl,--no-whole-archive
./libstaticSimulator.a 中的目标文件也是使用 -fPIC 标志编译的。此步骤工作正常,没有 compiler/linker 错误。我按照 a SO post 完成了这一步。
但是,当我尝试通过从 main 调用 sim 函数来测试共享库时遇到链接器错误:
g++ -O2 -g -m64 -Wall -fno-strict-aliasing -c -o main.o main.c
g++ -O2 -g -m64 -Wall -fno-strict-aliasing -L. main.o -o sim_dynlib -ldynamicSimulator -lm -lpthread
main.o: In function `main':
main.c:40: undefined reference to `sim(unsigned long*, unsigned long*, unsigned long*, unsigned long)'
collect2: error: ld returned 1 exit status
make: *** [sim_dynlib] Error 1
我用nm验证动态库中有这个符号:
$ nm ./libdynamicSimulator.so | grep sim
0000000000102e10 T sim
该库是用 C++ 编写的,但 sim 的名称没有被破坏,因为它是在 extern "C" 块中定义的:
extern "C" {
uint64_t sim(uint64_t *a1, uint64_t *a2, uint64_t *a3, uint64_t len)
{
...
}
}
下面是 main.c 声明和使用函数的方式:
extern uint64_t sim(uint64_t *a1, uint64_t *a2, uint64_t *a3, uint64_t len);
int main(int argc, char **argv)
{
... // preparing a1, a2, a3, len
uint64_t act_sum = sim(a1, a2, a3, len);
...
}
我在谷歌上搜索了几个小时试图找到问题,但我所能找到的只是关于重新排序 g++ 命令行中的 -l,我已经在 main.o 之后做了 --ldynamicSimulator。
我觉得我在这里确实遗漏了一些东西 simple/stupid 但对于我来说,我无法弄清楚它是什么。
感谢任何帮助或评论。
我想通了。我的感觉是正确的——这是一个愚蠢的错误:
main.c 中 sim() 函数的声明需要放在 extern "C" 块中,因为我使用 g++ 作为编译器。
extern "C" {
extern uint64_t sim(uint64_t *a1, uint64_t *a2, uint64_t *a3, uint64_t len);
}
int main(int argc, char **argv)
{
... // preparing a1, a2, a3, len
uint64_t act_sum = sim(a1, a2, a3, len);
...
}
此更改后链接器错误消失了。
另一个有效的简短声明:
extern "C" uint64_t sim(uint64_t *a1, uint64_t *a2, uint64_t *a3, uint64_t len);
我有一个包含简单模拟器的旧静态库。模拟器通过调用函数 (sim) 启动,该函数也包含在库中。现在,我想把这个静态库变成动态库:
g++ -shared -fPIC -o libdynamicSimulator.so -Wl,--whole-archive libstaticSimulator.a -Wl,--no-whole-archive
./libstaticSimulator.a 中的目标文件也是使用 -fPIC 标志编译的。此步骤工作正常,没有 compiler/linker 错误。我按照 a SO post 完成了这一步。
但是,当我尝试通过从 main 调用 sim 函数来测试共享库时遇到链接器错误:
g++ -O2 -g -m64 -Wall -fno-strict-aliasing -c -o main.o main.c
g++ -O2 -g -m64 -Wall -fno-strict-aliasing -L. main.o -o sim_dynlib -ldynamicSimulator -lm -lpthread
main.o: In function `main':
main.c:40: undefined reference to `sim(unsigned long*, unsigned long*, unsigned long*, unsigned long)'
collect2: error: ld returned 1 exit status
make: *** [sim_dynlib] Error 1
我用nm验证动态库中有这个符号:
$ nm ./libdynamicSimulator.so | grep sim
0000000000102e10 T sim
该库是用 C++ 编写的,但 sim 的名称没有被破坏,因为它是在 extern "C" 块中定义的:
extern "C" {
uint64_t sim(uint64_t *a1, uint64_t *a2, uint64_t *a3, uint64_t len)
{
...
}
}
下面是 main.c 声明和使用函数的方式:
extern uint64_t sim(uint64_t *a1, uint64_t *a2, uint64_t *a3, uint64_t len);
int main(int argc, char **argv)
{
... // preparing a1, a2, a3, len
uint64_t act_sum = sim(a1, a2, a3, len);
...
}
我在谷歌上搜索了几个小时试图找到问题,但我所能找到的只是关于重新排序 g++ 命令行中的 -l,我已经在 main.o 之后做了 --ldynamicSimulator。
我觉得我在这里确实遗漏了一些东西 simple/stupid 但对于我来说,我无法弄清楚它是什么。
感谢任何帮助或评论。
我想通了。我的感觉是正确的——这是一个愚蠢的错误:
main.c 中 sim() 函数的声明需要放在 extern "C" 块中,因为我使用 g++ 作为编译器。
extern "C" {
extern uint64_t sim(uint64_t *a1, uint64_t *a2, uint64_t *a3, uint64_t len);
}
int main(int argc, char **argv)
{
... // preparing a1, a2, a3, len
uint64_t act_sum = sim(a1, a2, a3, len);
...
}
此更改后链接器错误消失了。
另一个有效的简短声明:
extern "C" uint64_t sim(uint64_t *a1, uint64_t *a2, uint64_t *a3, uint64_t len);