web-dev-qa-db-ja.com

Cでコンパイルされた静的ライブラリをC ++プログラムにリンクする

静的ライブラリ(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を機能させるには、何かを追加する必要がありますか?
15
Prabu

問題は、階乗が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に変更します

23
john

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

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

1
Brett Hale