链接时g ++找不到符号

时间:2012-06-20 10:35:16

标签: gcc linker g++

好的,这可能是非常基本的,但我找不到问题。我正在尝试使用-lyajl将我的C ++程序与C共享库(YAJL命名)联系起来;链接器似乎找到它(它没有抱怨)但找不到我在我的代码中使用的符号:

$> 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 ++似乎无法正确做到?

2 个答案:

答案 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函数定义。