web-dev-qa-db-ja.com

C ++未定義の参照と静的ライブラリ

クラスから静的ライブラリを作成しようとしていますが、それを使用しようとすると、常に未定義の参照でエラーが発生します。私が進めた方法は、次のようなオブジェクトファイルを作成することでした

g++ -c myClass.cpp -o myClass.o

そして、それで梱包

ar rcs myClass.lib myClass.o

これには明らかに一般的に欠けているものがあります。シンボルのあるものだと思う。アドバイスをありがとう、私はそれがおそらくおそらく愚かなものに悩まされていくつかのチュートリアルを読んでいる場合、私が見つけることができるものであることを知っています:)

編集:

myClass.h:

class myClass{
    public:
        myClass();
        void function();
};

myClass.cpp:

#include "myClass.h"

myClass::myClass(){}
void myClass::function(){}

クラスを使用するプログラム:

#include "myClass.h"

int main(){
myClass mc;
mc.function();

return 0;
}

最後に、次のようにコンパイルします。

g++ -o main.exe -L. -l myClass main.cpp

エラーは古典的なものです:

C:\Users\RULERO~1\AppData\Local\Temp/ccwM3vLy.o:main.cpp:(.text+0x31): undefined
 reference to `myClass::myClass()'
C:\Users\RULERO~1\AppData\Local\Temp/ccwM3vLy.o:main.cpp:(.text+0x3c): undefined
 reference to `myClass::function()'
collect2: ld returned 1 exit status
46
Pyjong

これはおそらくリンク順序の問題です。 GNUリンカがライブラリを認識すると、必要のないすべてのシンボルが破棄されます。この場合、ライブラリは.cppファイルの前に表示されるため、ライブラリは。 cppファイルがコンパイルされます。

g++ -o main.exe main.cpp -L. -lmylib

または

g++ -o main.exe main.cpp myClass.lib

Microsoftリンカーは、コマンドラインでのライブラリの順序を考慮しません。

111
mch

別の考えられる原因:extern "C"を忘れています。

C++プログラムをC静的ライブラリにリンクしようとしたため、これに遭遇しました。ライブラリのヘッダーにはextern "C"がなかったため、リンカはマングルされた関数名を探していましたが、実際にはライブラリにはマングルされていない関数名がありました。

何が起こっているのかを理解するのに時間がかかったので、これが他の人の助けになることを願っています。

20
tprk77

これは、リンカが出力コードを最適化する方法の問題です。 Lib_ALib_Bの2つのライブラリを使用する実行可能ファイルがあるとします。 Lib_Aに依存Lib_BLib_Aはシンボルを定義します:Lib_A1およびLib_A2、およびLib_Bはシンボルを定義しますLib_B1およびLib_B2。ここで、実行可能ファイルがシンボルLib_A1のみを使用し、Lib_A1が使用すると仮定しますシンボルLib_B1Lib_Bで定義されています。シンボルLib_B1は、実行可能ファイルでは使用されません。

  1. ウィンドウの場合、リンカーは次のように機能します:いくつかのライブラリと実行可能ファイルで使用されるすべてのシンボルを使用する2つの実行可能ファイルがあり、すべてのライブラリはlib_A1およびlib_B1。したがって、これら2つのシンボルが必要になり、残りは不要です。定義解除しますlib_A2およびlib_B2
  2. Linuxの場合、リンクする場合Lib_B before Lib_Aこのように:g++ .... -lLib_B -lLib_Aリンカーは次のように機能します。最初にリンクする実行可能ファイルLib_Bがあります。実行可能ファイルでシンボルLib_B1Lib_B2も使用されていないことがわかります。それらは不必要なので、私はそれらを未定義にします。後でリンカーを参照してください。ああ、別のライブラリがありますLib_A。実行可能ファイルはシンボルLib_B1を使用していることがわかります。そのままにして未使用のシンボルの定義を解除しますLib_B2Lib_B1Lib_A1を使用していることがわかりません。
  3. Linuxの場合、Lib_Aの前にLib_Bをリンクすると、次のようになります:g++ ... -lLib_A -lLib_Bリンカーは次のように機能します。最初にリンクする実行可能ファイルLib_Aがあります。ああ、実行可能ファイルはLib_A1を使用していることがわかります。それらを保持し、未定義にしますLib_A2。後で見ることができます。ああ、別のライブラリがありますLib_B。既にリンクされたシンボルで実行可能になり、Lib_B1を使用していることがわかります。その結果、Lib_B1Lib_A1、未定義Lib_B2およびLib_A2
6
Grzegorz Dymek

使用する:

g++ -o main.exe main.cpp myClass.lib 

ライブラリパスと-lフラグの使用には問題が伴いますが、必要な場合は、ライブラリの名前をlibmylib.aに変更し、次のようにコンパイルします。

g++ -o main.exe main.cpp -L. -lmylib 

また、移植性の理由から、ソースファイルまたは出力ファイルの名前に大文字と小文字を混在させることは一般的に悪い考えです。

5
anon

これにより、リンクエラーが回避され、.so共有ライブラリが作成されます。

LOCAL_ALLOW_UNDEFINED_SYMBOLS := true
1
Oshi