Pertimbangkan program level API Windows berikut:
#define NOMINMAX
#include <windows.h>
int main()
{
MessageBox( 0, "Blah blah...", "My Windows app!", MB_SETFOREGROUND );
}
Sekarang mari kita membangunnya menggunakan GNU toolchain (yaitu g ++), tanpa opsi khusus. Ini gnuc
hanya file batch yang saya gunakan untuk itu. Ini hanya menyediakan opsi untuk membuat g ++ lebih standar:
C: \ test> gnuc x.cpp
C: \ test> objdump -x a.exe | findstr / i "^ subsistem"
Subsistem 00000003 (Windows CUI)
C: \ test> _
Ini berarti bahwa linker secara default menghasilkan subsistem konsol yang dapat dieksekusi. Nilai subsistem di header file memberi tahu Windows layanan apa yang dibutuhkan program. Dalam hal ini, dengan sistem konsol, program tersebut memerlukan jendela konsol.
Ini juga menyebabkan penerjemah perintah menunggu program selesai.
Sekarang mari kita membangunnya dengan subsistem GUI , yang artinya program tidak memerlukan jendela konsol:
C: \ test> gnuc x.cpp -mwindows
C: \ test> objdump -x a.exe | findstr / i "^ subsistem"
Subsistem 00000002 (Windows GUI)
C: \ test> _
Mudah-mudahan tidak apa-apa sejauh ini, meskipun -mwindows
benderanya hanya setengah terdokumentasi.
Membangun tanpa bendera semi-terdokumentasi itu, seseorang harus lebih spesifik memberi tahu linker nilai subsistem mana yang diinginkan, dan beberapa pustaka impor Windows API secara umum harus ditentukan secara eksplisit:
C: \ test> gnuc x.cpp -Wl, -subsystem, windows
C: \ test> objdump -x a.exe | findstr / i "^ subsistem"
Subsistem 00000002 (Windows GUI)
C: \ test> _
Itu bekerja dengan baik, dengan toolchain GNU.
Tapi bagaimana dengan toolchain Microsoft, yaitu Visual C ++?
Nah, membangun sebagai subsistem konsol yang dapat dieksekusi berfungsi dengan baik:
C: \ test> pnidui x.cpp user32.lib
x.cpp
C: \ test> dumpbin / headers x.exe | temukan / i "subsistem" | temukan / i "Windows"
3 subsistem (Windows CUI)
C: \ test> _
Namun, dengan pembangunan toolchain Microsoft sebagai subsistem GUI tidak berfungsi secara default:
C: \ test> pnidui x.cpp user32.lib / link / subsistem: windows
x.cpp
LIBCMT.lib (wincrt0.obj): error LNK2019: simbol eksternal belum terselesaikan _WinMain @ 16 direferensikan dalam fungsi ___tmainCRTStartu
p
x.exe: kesalahan fatal LNK1120: 1 eksternal yang belum terselesaikan
C: \ test> _
Secara teknis ini karena linker Microsoft non-standar secara default untuk subsistem GUI . Secara default, jika subsistemnya adalah GUI, maka linker Microsoft menggunakan titik masuk pustaka runtime , fungsi tempat eksekusi kode mesin dimulai, disebut winMainCRTStartup
, yang memanggil non-standar Microsoft, WinMain
bukan standar main
.
Bukan masalah besar untuk memperbaikinya.
Yang harus Anda lakukan adalah memberi tahu tautan Microsoft titik masuk mana yang akan digunakan, yaitu mainCRTStartup
yang memanggil standar main
:
C: \ test> pnidui x.cpp user32.lib / link / subsistem: windows / entry: mainCRTStartup
x.cpp
C: \ test> dumpbin / headers x.exe | temukan / i "subsistem" | temukan / i "Windows"
2 subsistem (Windows GUI)
C: \ test> _
Tidak masalah, tapi sangat membosankan. Dan begitu misterius dan tersembunyi sehingga sebagian besar programmer Windows, yang kebanyakan hanya menggunakan alat non-standar-oleh-default Microsoft, bahkan tidak mengetahuinya, dan secara keliru berpikir bahwa program subsistem GUI Windows “harus” memiliki non-standar dan WinMain
bukan standar main
. Secara sepintas, dengan C ++ 0x Microsoft akan memiliki masalah dengan ini, karena kompiler harus mengiklankan apakah itu berdiri bebas atau dihosting (ketika dihosting harus mendukung standar main
).
Bagaimanapun, itulah alasan mengapa g ++ dapat mengeluh tentang WinMain
hilang: ini adalah fungsi startup non-standar yang konyol yang diperlukan alat Microsoft secara default untuk program subsistem GUI.
Tetapi seperti yang Anda lihat di atas, g ++ tidak memiliki masalah dengan standar main
bahkan untuk program subsistem GUI.
Jadi apa masalahnya?
Nah, Anda mungkin melewatkan file main
. Dan Anda mungkin juga tidak memiliki (yang layak) WinMain
! Dan kemudian g ++, setelah mencari main
(tidak ada), dan non-standar Microsoft WinMain
(tidak seperti itu), melaporkan bahwa yang terakhir hilang.
Menguji dengan sumber kosong:
C: \ test> ketik nul> y.cpp
C: \ test> gnuc y.cpp -mwindows
c: / berkas program / mingw / bin /../ lib / gcc / mingw32 / 4.4.1 /../../../ libmingw32.a (main.o): main.c :(. teks + 0xd2 ): rujukan yang tidak ditentukan
ce ke `WinMain @ 16 '
collect2: ld mengembalikan 1 status keluar
C: \ test> _
All you have to do is to tell Microsoft's linker which entry point to use, namely mainCRTStartup, which calls standard main
. Apakah ada cara untuk melakukan ituEclipse CDT
karena saya tidak menggunakan baris perintah. Terima kasih