静的ライブラリ(gccでコンパイル)をc ++プログラムにリンクしようとすると、「未定義の参照」が発生しました。私はubuntu12.04サーバーマシンでgccとg ++バージョン4.6.3を使用しました。たとえば、階乗メソッドの単純なライブラリファイルは次のとおりです。
mylib.h
#ifndef __MYLIB_H_
#define __MYLIB_H_
int factorial(int n);
#endif
mylib.c
#include "mylib.h"
int factorial(int n)
{
return ((n>=1)?(n*factorial(n-1)):1);
}
Gccを使用してこのmylib.cのオブジェクトを作成しました。
gcc -o mylib.o -c mylib.c
ここでも、静的ライブラリはARユーティリティを使用してオブジェクトファイルから作成されました。
ar -cvq libfact.a mylib.o
このライブラリをCプログラム(test.c)とC++プログラム(test.cpp)でテストしました
CプログラムとC++プログラムはどちらも同じ本体を持っています。
#include "mylib.h"
int main()
{
int fact = factorial(5);
return 0;
}
静的ライブラリlibfact.aが/ home/testディレクトリにあると仮定して、Cプログラムを問題なくコンパイルしました。
gcc test.c -L/home/test -lfact
ただし、C++プログラムのテスト中に、リンクエラーが発生しました。
g++ test.cpp -L/home/test -lfact
test.cpp:(.text+0x2f): undefined reference to `factorial(int)'
collect2: ld returned 1 exit status
Test.cppにexternコマンドを追加してみました。
extern int factorial(int n) //added just before the main () function
それでも同じエラー。
test.cpp
を機能させるには、何かを追加する必要がありますか?問題は、階乗がCで記述されていることをC++プログラムに伝えていないことです。test.hヘッダーファイルを変更する必要があります。このような
#ifndef __MYLIB_H_
#define __MYLIB_H_
#ifdef __cplusplus
extern "C" {
#endif
int factorial(int n);
#ifdef __cplusplus
}
#endif
#endif
これで、ヘッダーファイルはCプログラムとC++プログラムの両方で機能するはずです。詳細については、 ここ を参照してください。
ところで、二重下線を含む名前は準拠者用に予約されているため(下線と大文字で始まる名前も同様)、厳密に言えば#ifndef __MYLIB_H_
は違法です。 #ifndef MYLIB_H #define MYLIB_H
に変更します
受け入れられた答えは絶対に正しいですが、私はただ観察を追加したいと思いました。一部のエディターは、中括弧の開閉に問題があり、ヘッダーのextern "C"
スコープ全体をインデントします。 mylib.h
がライブラリのキーヘッダーである場合は、次のことを検討してください。
#if defined (__cplusplus)
#define _MYLIB_INIT_DECL extern "C" {
#define _MYLIB_FINI_DECL }
#else
#define _MYLIB_INIT_DECL
#define _MYLIB_FINI_DECL
#endif
mylib
ライブラリ内の他のすべてのヘッダー(例:mylib_aux.h
)は、次の形式にすることができます。
#ifndef _MYLIB_AUX_H
#define _MYLIB_AUX_H
#include <mylib.h>
_MYLIB_INIT_DECL
... header content ...
_MYLIB_FINI_DECL
#endif /* _MYLIB_AUX_H */
明らかに、私が使用している名前は任意ですが、複数のライブラリヘッダーの場合、このアプローチは私にとって便利です。