19

スタティック ライブラリ (gcc でコンパイル) を C++ プログラムにリンクしようとしたところ、「未定義の参照」が発生しました。ubuntu 12.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必要がありますか?
4

2 に答える 2

28

問題は、factorial が 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++ の両方のプログラムで機能するはずです。詳しくはこちらをご覧ください。

ところで、2 つのアンダースコアを含む名前はコンパイラ用に予約されているため (アンダースコアと大文字で始まる名前も同様です)、#ifndef __MYLIB_H_厳密に言えば違法です。私はに変更します#ifndef MYLIB_H #define MYLIB_H

于 2013-09-28T06:25:33.217 に答える
1

受け入れられた答えは絶対に正しいですが、観察を追加するだけだと思いました。一部のエディターは開き括弧と閉じ括弧に問題があり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 */

明らかに、私が使用している名前は任意ですが、複数のライブラリ ヘッダーの場合、このアプローチは役に立ちました。

于 2013-09-28T08:42:19.353 に答える