$> g++ test.c -lyajl
Undefined symbols for architecture x86_64:
"yajl_tree_parse(char const*, char*, unsigned long)", referenced from:
_main in ccEqsAaJ.o
"yajl_tree_get(yajl_val_s*, char const**, yajl_type)", referenced from:
_main in ccEqsAaJ.o
"yajl_tree_free(yajl_val_s*)", referenced from:
_main in ccEqsAaJ.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
$>
我创建了一个极简主义的test.c文件来隔离行为。嗯,非常奇怪的是gcc在代码中似乎完全没问题(因为顺便提一句,test.c只是C代码,这里没有C ++特性):
$> gcc test.c -lyajl
$>
gcc在做什么,g ++似乎无法正确做到?
答案 0 :(得分:4)
可能是libyajl.so中的符号是C链接,但是您的代码(或您正在使用的头文件)没有声明它们extern "C"
?在这种情况下,将代码编译为C ++将导致目标文件中出现name-mangled symbols,这与库中的(C链接,未校正的)符号不匹配。
解决方案是在头文件中写下这样的内容:
#ifdef __cplusplus
// "__cplusplus" is defined whenever it's a C++ compiler,
// not a C compiler, that is doing the compiling.
extern "C" {
#endif
// Exchange "void" with the real return type for these functions
void yajl_tree_parse(char const*, char*, unsigned long);
void yajl_tree_get(yajl_val_s*, char const**, yajl_type);
void yajl_tree_free(yajl_val_s*);
#ifdef __cplusplus
}
#endif
答案 1 :(得分:3)
如果extern "C"
无法修复,请尝试此操作。
我在尝试链接静态库时遇到了同样的问题 - libyajl_s.a。 通过将yajl源编译为可执行文件,可以解决该问题, 但我真的需要静态库。 仔细检查yajl源后,您将看到源正在两个单独的文件夹中查找标题,例如
#include <api/yajl_tree.h>
#include <api/yajl_parse.h>
#include "yajl_parser.h"
链接器似乎将yajl_tree_parse,yajl_tree_get和yajl_tree_free解析为yajl_tree.h中的原型,而不是yajl_tree.c中的定义。换句话说 - 它们在生成的库中保持未定义。
解决方案是将所有标头从 api 文件夹移动到 src 文件夹中,并删除对<api/...>
的所有引用。然后,链接器正确地选择了yajl_tree_xxx函数定义。