2011-12-24 13 views
1

私はそれは私が必要なすべてのだったが、コンパイラが文句を望んCヘッダファイルの含めると一緒にC++ヘッダにラインextern "C" void perlinTest(void);を追加しました:それはライブラリではない場合、あなたがいずれかを必要としないiPhoneのC++コードからC関数をどのように呼び出すのですか?

Undefined symbols for architecture i386: 
    "perlinTest()", referenced from: 
     CreateRenderer3(IResourceManager*) in Renderer.o 
+1

また、その機能を提供するライブラリにリンクする必要があります。 – Mat

+0

これはライブラリではありません。私はc関数とそれを呼び出すC++コードの両方を書きました。 – Xavier

+0

次に、Cコードがコンパイルされ、C++コードとリンクされていることを確認する必要があります。 – Mat

答えて

1

C++コードは関数がC関数であることを認識する必要があります。状況に現実的な例は以下のようになり

extern "C" [prototype]; 

:これを行うには、あなたはそれをこのように宣言する必要があり

extern "C" void perlinTest(); 

この理由はC++ function names are mangledその種類について告げる何かにありますパラメータ。最も低いレベルでは、オーバーロードが許可されています。同じ名前を持つ2つのシンボルを表示することは合理的ではないため、C++では、関数名にパラメータのタイプを示すマーカーを埋め込むことができます。たとえば、void perlinTest()は、g++(おそらくはclang++)のLionボックスに_Z10perlinTestvと表示されますが、これはABI固有であり、他のプラットフォームでは必ずしも同じではありません。

しかし、Cはオーバーロードをサポートしておらず、関数は名前のマングリングの対象ではないため、C++コードを呼び出そうとするときには、名前が変更された名前を使用してはならないことを知る必要があります。これは、extern "C"がコンパイラに指示するものです。

あなたのヘッダファイルは、CおよびC++の両方から読めるようにする必要がある場合は、一般的な方法はextern "C"ブロックでそれらをラップすることです(extern "C" { /* declarations */ })自体が(そのCコードがextern "C"を見ていない#ifdef __cplusplusプリプロセッサディレクティブに包まれてコード)。

#ifdef __cplusplus 
extern "C" { 
#endif 

/* header body */ 

#ifdef __cplusplus 
} 
#endif 
0

extern C.これは.cファイルの拡張子に変わり、どのようにコンパイラがそれを認識するように設定されているか(.cコードではないように見えます)

0

実際にvoid perlinTest(void)を実装しましたか。

最初は、実際に実装することなく、単に関数を宣言することができます。あなたの他のクラス/オブジェクトが実際にperlinTest()を呼び出すことがない場合、Xcodeはあなたのアプリを喜んでビルドして実行し、エラーを出さないでしょう。 perlinTest()は実際にどこからでも参照されていないので、関数が実際に実装されていないかどうかは気にしません。

とすぐに(CreateRenderer3(IResourceManager*) in Renderer.oからのような)あなたの他のクラスの1からperlinTest()を呼び出そうとしていると、リンカはそのシンボルが解決できることを確認したくなるでしょうし、あなたが実際にそれを必要最小限の定義を実装していない場合(下記参照)、あなたが持っているようなエラーが出る可能性があります。

リンクエラーを防止する必要があり、次のような最小限の実装:あなたはこれをデバッグするために使用することができます

void perlinTest(void) { 

} 
+0

はい私はそれを実装しました。 – Xavier

0

1つのトリックは、あなたのperlinTest()関数内で意図的にエラーを導入することです。次に、あなたのアプリケーションを構築し、コンパイラがエラーを報告するかどうかを確認します。とにかくアプリケーションがコンパイルされた場合、問題は、この関数を持つファイルが、ビルドしているターゲットの一部ではないということです。

貼り付けたエラーはi386アーキテクチャ用であるため、iPhoneにすることはできません。あなたはおそらくiPhoneシミュレータのためにビルドしています。

編集:次の手順では、Xcodeによって発行されたリンクコマンドにC関数を持つ.oが含まれていることを確認します。そうであれば、.oファイルの内容をnmユーティリティーでダンプして、.oファイル内の関数名がどのようになっているかを確認する必要があります。

+0

エラーが発生した後、perlinTestを含むファイルがコンパイルされませんでした。 – Xavier

+0

はい私はiPhoneシミュレータ用にコンパイルしています。 – Xavier

関連する問題