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 kasihmain
atau aWinMain
, atau, pastikan bahwa file yang relevan disertakan dalam proyek. Cheers,main
atauwinmain
? Terima kasihUntuk meringkas posting di atas oleh Cheers dan hth. - Alf, Pastikan Anda memiliki
main()
atauWinMain()
mendefinisikan dan g ++ harus melakukan hal yang benar.Masalah saya adalah yang
main()
didefinisikan di dalam namespace secara tidak sengaja.sumber
Saya mengalami kesalahan ini saat menyusun aplikasi saya dengan SDL. Hal ini disebabkan oleh SDL yang mendefinisikan fungsi utamanya sendiri di SDL_main.h. Untuk mencegah SDL menentukan fungsi utama, makro SDL_MAIN_HANDLED harus ditentukan sebelum header SDL.h disertakan.
sumber
Coba simpan file .c Anda sebelum membangun. Saya yakin komputer Anda mereferensikan jalur ke file tanpa informasi di dalamnya.
--Memiliki masalah serupa saat membangun proyek C.
sumber
Periksa bahwa Semua File Disertakan dalam Proyek Anda:
Saya mengalami kesalahan yang sama muncul setelah saya memperbarui cLion. Setelah berjam-jam mengutak-atik, saya melihat salah satu file saya tidak termasuk dalam target proyek. Setelah saya menambahkannya kembali ke proyek aktif, saya berhenti mendapatkan referensi yang tidak ditentukan ke winmain16, dan kode dikompilasi.
Edit: Ini juga bermanfaat untuk memeriksa pengaturan build dalam IDE Anda.
(Tidak yakin apakah kesalahan ini terkait dengan pembaruan IDE - bisa jadi kausal atau korelatif. Jangan ragu untuk berkomentar dengan pemahaman apa pun tentang faktor itu!)
sumber