3

簡単なプログラムを考えると:

#include <windows.h>

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hInstPrev, 
                   LPSTR lpCmdLine, int nCmdShow)
{
  return 0;
}

実行すると正常に動作g++ a.cppします。

ただし、実行g++ -c a.cpp && ar rcs a.a a.o && g++ a.aすると次のエラーが発生します。

c:/mingw32/bin/../lib/gcc/i686-w64-mingw32/4.8.1/../../../../i686-w64-mingw32/lib/../lib/libmingw32.a(lib32_libmingw32_a-crt0_c.o):crt0_c.c:(.text.startup+0x39): undefined reference to `WinMain@16'
collect2.exe: error: ld returned 1 exit status

なぜこれが起こるのかについての洞察はありますか?.a ファイルのみのプログラムをリンクするにはどうすればよいですか?

4

3 に答える 3

7

gccldリンカーは、静的ライブラリをオブジェクト ファイル*.aとは少し異なる方法で処理します。*.o特に、スタティック ライブラリのシンボルは、以前にリンクされたオブジェクト ファイルまたは別のスタティック ライブラリで使用されない限り、最終的なバイナリ イメージ実行可能ファイルに含まれません。

さらに、静的ライブラリで渡す順序は にとって重要ですld。たとえば、 にlibb.aある関数が必要だとしますliba.a。次のようにリンクすると:

g++ -Wall example.cpp -o example.exe -la -lb

が処理されたときに、必要libaなシンボルが認識されない (まだ処理されていない)ため、これは解決できません。から取得される唯一のシンボルは、それまでに見たすべてのものです-lblibbliba.a

何でこれが大切ですか?

上記のプロセスを質問に適用すると、WinMain解決されない理由が明らかになります。

g++ aa

ldプロセス時a.aに、「ああ、何も使用しWinMainていないので、含めません」と表示されます。その前に他のオブジェクトファイルが提供されていないため、それは処理のその時点まで当てはまります。

上に表示されていないのは、mingw には、デフォルトで、プログラムが動作するために必要な一連の重要なボイラープレート コードも含まれているということです。これらの 1 つは、crt0_c.oあなたのを呼び出すmingwmingw32.aランタイムの一部を構成するものです。WinMain

ソリューション

WinMainfroma.aが含まれていることを確認するには、次の 2 つの方法があります。

  1. シンボルの解決に使用できるように-Wl,--whole-archive、すべてのシンボルを強制的に含めるa.aために使用します。後で追加して、後に続く-Wl,--no-whole-archive他のライブラリに誤って適用しないようにします。例えば。

    g++ -o example.exe -Wl,--whole-archive a.a -Wl,--no-whole-archive
    
  2. 2 番目の方法は、soが処理されたときに保留中の未解決のシンボルになるmingw32.aに手動で含めることです。 a.aWinMaina.a

    g++ -o example.exe -lmingw32 a.a
    

    また

    g++ -o example.exe libmingw32.a a.a
    

ただし、おそらくパスを完全に修飾する必要がありますlibmingw32.a。そうしないと、リンカーがパスを見つけられません。

于 2013-10-29T02:12:54.807 に答える
0

Code::Blocks を使用しています。今日、私は静的ライブラリの WinMain で同じ問題を抱えています。私の場合、ライブラリの順序を変更しても機能しません。Project/Build options/Linker settings/Other linker options-lmingw32に追加することで最終的に解決しました

于 2014-07-22T18:07:53.317 に答える
0

リンカーに関する限り、.a ファイルは静的ライブラリです。リンカーは、現在未解決のシンボルを定義するオブジェクトのみをアーカイブから取り出します。したがって、.a ファイルで定義されたシンボルを参照するオブジェクト ファイルがなければ、それらは取り込まれません。この例のリンカー出力は空であるため、WinMain は定義されていません。

実際には、標準の main() を定義すると機能するように見えます。これは、言語標準で必要な main() への参照があるためだと思います。シンボルへの参照を生成する gcc / ld コマンド ライン オプションもあります。-u WinMain@16.a ファイルの前に追加してみてください。

于 2013-10-27T23:48:32.480 に答える