21


7

私はgccで使用するcライブラリを持っています。 ライブラリの拡張子は .lib but is always linked as a static library. If i write a program これは、ライブラリをCコードとして、すべてをOKとして使用します。 ただし、ファイル名を.cppに変更した場合(両方のc / cで機能する単純なことをしている場合)、未定義の参照が表示されます。 これらは私がテスト目的のために書いた単純な小さなプログラムですので空想的なものはありません。 私はコンパイルします:

gcc -g -Wall -I -oプログラムmain.c customlibrary.lib -lm -lpthread

上記は魅力的です。 しかしながら:

g -g -Wall -I -oプログラムmain.cpp customlibrary.lib -lm -lpthread

または

gcc -g -Wall -I -oプログラムmain.cpp customlibrary.lib -lm -lpthread -lstdc

customlibrary.lib内の関数への未定義の参照が発生します。 私はcustomlibrary.aという名前のシンボリックリンクを作成しようとしましたが、運が悪いです。

私のライブラリを認識できないのはなぜですか。 残念ながら、ライブラリのソースコードにアクセスすることはできませんが、c-libをcにリンクしても問題ないはずです。

3 回答


38


あなたのライブラリは、CではなくCから呼び出されることを想定したAPIを持っているようです。 Cは、ライブラリからエクスポートされたシンボルに、関数名だけではなくより多くの情報が含まれることを事実上必要とするため、これは重要です。 これは、関数の「名前マングリング」によって処理されます。

あなたのライブラリには、そのパブリックインタフェースを宣言するインクルードファイルがあると思います。 CとCの両方と互換性を持たせるために、宣言する関数はCのリンケージと命名を使用すると想定されるべきであることをCコンパイラに伝えるように手配する必要があります。

これをテストするための最も簡単な答えは、これを行うことです。

extern "C" {
#include "customlibrary.h"
}

`+ customlibrary.h +`を直接インクルードする代わりに、main.cppで。

ヘッダ自体を両方の言語で動作させ、その関数をCに似たCとして正しく宣言するには、ヘッダファイルの先頭近くに次の行を追加します。

#ifdef __cplusplus
extern "C" {
#endif

そして、底の近くに以下があります:

#ifdef __cplusplus
}
#endif


4


Cコンパイラは、名前マングリングと呼ばれるものを実行します。コードに表示される名前は、リンカと同じ名前ではありません。 これを回避する通常の方法は、特定の関数にCリンケージが必要であることをコンパイラーに伝えることです。

// myfile.cpp
extern "C" int libfun(); //ライブラリ内のC関数

またはヘッダファイル全体に対してそれを実行します。

// myfile.cpp
extern "C" {#include "mylibdefs.h" // Cライブラリ関数用のdefs}


2


あなたのヘッダファイルは普通の

#ifdef __cplusplus extern "C" {#endif

// ...

#ifdef __cplusplus} / * extern "C" * / #endif

ライブラリ関数に明示的にCリンケージを与える。