2011-07-27 12 views
3

私は入門チュートリアルhttp://www.linuxinsight.com/files/alp/alp-ch01-getting-started.pdfに従っています。C++ヘッダーを使用した単純なCプログラムのリンクエラー

ソースファイルmain.c、reciprocal.cpp、およびreciprocal.hppを作成しました。これらのファイルを正常にコンパイルできました。私はそれらをリンクするために行くと、私は次のエラーメッセージが表示されたときに問題が来る:

main.o: In function `main': 
main.c:(.text+0x30): undefined reference to `reciprocal' 
collect2: ld returned 1 exit status 

私はしかし、私は本当に私がきたようにしようとするのか分からない、これは何とか正しくヘッダファイルを使用していないことを集めますステップをかなり徹底的に続けました。

誰かがそのエラーを投げる理由を知っていれば、私は非常に感謝します。

おかげ

**ここでUPDATE は、3つのソースファイルのコードです:

main.cの

#include <stdio.h> 
#include "reciprocal.hpp" 

int main (int argc, char **argv) { 
    int i; 
    i = atoi(argv[1]); 
    printf("The reciprocal of %d is %g\n", i, reciprocal(i)); 

    return 0; 
} 

reciprocal.cpp

#include <cassert> 
#include "reciprocal.hpp" 

double reciprocal(int i) { 
    assert(i != 0); 
    return 1.0/i; 
} 

reciprocal.hpp

#ifdef __cplusplus 
extern "C" { 
#endif 

double reciprocal(int i); 

#ifdef __cplusplus 
} 
#endif 

私は実際に投稿してからreciprocal.hppを実際に変更しました。私が行った唯一の変更は、関数の署名からexternキーワードを削除することでした。これまでに読んだ

extern double reciprocal(int i); 

この変更により、プログラムをリンクすることができ、今すぐ実行することができます。私は起こっているかもしれないと思うのは、2番目のexternが最初のexternを上書きしていたということです。誰かがこれについての洞察を持っているなら、私は知ることに興味があるでしょう。

ご協力いただきありがとうございます。

+1

自分のファイルのコードを入力してください。 – Pepe

+1

これをコンパイルするために使用している行を表示できますか? reciprocal.cppはコンパイルされていないか、リンクされていないようなサウンドです。 –

答えて

5

CとC++コードを混在させると、2つの言語が異なるリンケージを持っているため、問題が発生する可能性があります。つまり、コンパイル済みのCおよびC++ファイルのオブジェクトファイルを開かないと、それらのオブジェクトファイル内の名前が異なることがわかります。

特に、C++コンパイラでは、関数名に引数の型に関する追加情報が混在する「名前の変更」というテクニックを使用する傾向があります。例えば、機能

char foo(int); 

は、実際に内部名

[email protected]@int 

生成されたオブジェクトファイルの内部を持っているかもしれません。問題はCコードではこれが行われないため、Cファイルをコンパイルして、fooという名前の参照を作成しようとすると、生成されたC++ファイル内の関数の名前が[email protected]@intであるため、 fooの代わりに

これを修正するために、C++には、リンカーに名前を変更しないように明示し、生成されたコードをCプログラムのように見せる機能があります。これを行うには、次のようにC++の関数を宣言することができます。

extern "C" char foo(int); 

は今、生成されたオブジェクトファイルは、Cのコードが期待するものと互換性のある方法で装飾することなく、名前fooが含まれています。

問題を解決するには、extern "C"宣言のいずれかをreciprocalを定義するC++ソースファイルに追加してみてください。

注:CおよびC++コードをミックスプロジェクトを持っている場合、あなたは常には、C++コードとしてコンパイルmain機能を持っている必要があります。 C++は、Cコードには存在しない実行可能ファイルに追加の初期化とクリーンアップコードを導入しています。 mainをCコードとしてコンパイルすると、この余分なロジックがプログラムに追加されない可能性があり、実行時に不明なクラッシュが発生する可能性があります。

希望すると便利です。

+0

ありがとうございましたこれは私がこのFAQを読んで正しい解決策を見つけることに私を導きます:http://www.parashift.com/c++-faq-lite/mixing-c-and-cpp.html –

1

C++ファイルをCファイルにリンクすることは、最高で難しいです。 C++は、オーバーロードが発生するように名前を「mangles」します。

あなたはこのようなあなたの逆数で定義を囲むことにより、マングリングを防ぐことができます。

extern "C" { 
    reciprocal definition... 
} 

は、あなたがこれを行う場合は、あなたにもちょうど... Cでそれを書くかもしれません

あなたが作ることができますmain.cppファイル?

1

reciprocal.hppの内容が無効で、#ifdef行の入力ミスが__cplusplusと正しく表示されています(2つのアンダースコアが必要です)。

+0

洞察力をありがとう。 –

関連する問題