0

次の手順で共有ライブラリを構築しています。

cc -shared -Wl,-soname,libmy.so.0 [lots of .o files] -o libmy.so.0
ln -f -s libmy.so.0 libmy.so

これが重要かどうかはわかりませんが、このライブラリは C で書かれています。

次に、C++ プログラムからこのライブラリにリンクしようとします。

/usr/bin/c++ -g CMakeFiles/codegen.dir/client/codegen.cpp.o CMakeFiles/codegen.dir
 /namenode/shared_objects.cpp.o  -o codegen -rdynamic -L/path/to/libmy -lpthread
 -lboost_system-mt -lboost_filesystem-mt -lboost_unit_test_framework-mt
 -lboost_serialization-mt -lmy -Wl,-rpath,/path/to/libmy

しかし ld はエラーを報告します:

CMakeFiles/codegen.dir/client/codegen.cpp.o: In function `main':
[...]/src/client/codegen.cpp:46:
   undefined reference to `alloc_code(int, int, int, int, int)'

alloc_code共有ライブラリにあるように見えても:

$ nm libmy.so | grep alloc_code
0000000000002c80 T alloc_code

libmy.so私のプログラムは異なるコンパイラフラグを使用してコンパイルされていることに注意してくださいcodegen(1つはデバッグモードでコンパイルされ、もう1つは最適化モードでコンパイルされます)が、問題はここから来るとは思いません。

ldリンクできない原因は何ですか?codegenlibmy.so

4

1 に答える 1

1

C 関数は、次のように C++ に宣言する必要があります。

#ifdef __cplusplus
extern "C" {
#endif

void alloc_code(int, int, int, int, int);

#ifdef __cplusplus
}
#endif

それ以外の場合、コンパイラとリンカーは C++ リンケージ (引数が異なる限り、複数の関数が同じ名前で存在できる場合) を想定し、関数の "C++ マングル" バリアントを検索します。

使用するときextern "C"は、コンパイラとリンカーに、マングルされていない「C」名を使用するように指示します。

これを実証するために、同じ「ライブラリ」を作成し、C コンパイラと C++ コンパイラの両方でコンパイルしてみましょう。

/* Library Source Code */
int library_function(void) {
    return 0;
}

次に、C でコンパイルします。

gcc -o libdummy.so -shared -fPIC dummy-library.c
nm libdummy.so | grep library_function

どの出力:

0000000000000640 T library_function

C++ コンパイラで同じことを実行すると、次の結果が得られます。

g++ -o libdummy.so -shared -fPIC dummy-library.c
nm libdummy.so

=>

0000000000000670 T _Z16library_functionv
于 2013-10-01T16:46:05.383 に答える