3

OK、これはおそらく非常に基本的なものですが、問題が見つかりません。-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
$>

g++ が正しく実行できないと思われる gcc の動作は何ですか?

4

2 に答える 2

4

libyajl.soのシンボルがCリンケージであるが、コード(または使用しているヘッダーファイル)がそれらを宣言していない可能性がありますextern "C"か?その場合、コードをC ++としてコンパイルすると、オブジェクトファイル内の名前がマングルされたシンボルになり、ライブラリ内の(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
于 2012-06-20T10:44:55.190 に答える
3

extern "C"解決しない場合は、これを試してください。

静的ライブラリ libyajl_s.a にリンクしようとして同じ問題が発生しました。yajl ソースを実行可能ファイルにコンパイルすることで問題を回避することは可能ですが、静的ライブラリが本当に必要でした。yajl ソースを詳しく調べると、ソースが 2 つの別々のフォルダーでヘッダーを探していることがわかります。

#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.c の定義ではなく、yajl_tree.h のプロトタイプに解決するようです。つまり、結果のライブラリでは未定義のままです。

解決策は、すべてのヘッダーをapiフォルダーからsrcフォルダーに移動し、へのすべての参照を削除することでした<api/...>。その後、リンカは yajl_tree_xxx 関数定義を正しく取得しました。

于 2012-09-20T10:32:04.060 に答える