Yanıtlar:
Aşağıdaki Windows API düzeyindeki programı düşünün:
#define NOMINMAX
#include <windows.h>
int main()
{
MessageBox( 0, "Blah blah...", "My Windows app!", MB_SETFOREGROUND );
}
Şimdi onu GNU araç zincirini (yani g ++) kullanarak oluşturalım, özel seçenekler yok. Burayagnuc
bunun için kullandığım bir toplu iş dosyası. Yalnızca g ++ 'yı daha standart hale getirmek için seçenekler sağlar:
C: \ test> gnuc x.cpp C: \ test> objdump -x a.exe | findstr / i "^ altsistem" Alt sistem 00000003 (Windows CUI) C: \ test> _
Bu, bağlayıcının varsayılan olarak çalıştırılabilir bir konsol alt sistemi ürettiği anlamına gelir . Alt sistem dosyası başlığında değer programı gerektirir hangi hizmetlerin Windows bildirir. Bu durumda, konsol sistemiyle, programın bir konsol penceresi gerektirmesi.
Bu aynı zamanda komut yorumlayıcısının programın tamamlanmasını beklemesine neden olur.
Şimdi bunu GUI alt sistemi ile oluşturalım , bu sadece programın bir konsol penceresi gerektirmediği anlamına gelir:
C: \ test> gnuc x.cpp -mwindows C: \ test> objdump -x a.exe | findstr / i "^ altsistem" Alt sistem 00000002 (Windows GUI) C: \ test> _
-mwindows
Bayrak sadece yarı belgelenmiş olmasına rağmen umarım şimdiye kadar sorun olmaz .
Bu yarı belgelenmiş bayrak olmadan inşa etmek, bağlayıcıya hangi alt sistem değerini istediğini daha spesifik olarak söylemek zorunda kalacak ve bu durumda bazı Windows API içe aktarma kitaplıklarının genel olarak açıkça belirtilmesi gerekecektir:
C: \ test> gnuc x.cpp -Wl, -subsystem, windows C: \ test> objdump -x a.exe | findstr / i "^ altsistem" Alt sistem 00000002 (Windows GUI) C: \ test> _
Bu, GNU araç zinciri ile iyi çalıştı.
Peki ya Microsoft araç zinciri, yani Visual C ++?
Bir konsol alt sistemi yürütülebilir dosyası olarak oluşturmak iyi çalışıyor:
C: \ test> msvc x.cpp user32.lib x.cpp C: \ test> dumpbin / başlıklar x.exe | / i "alt sistem" bul | bul / i "Windows" 3 alt sistem (Windows CUI) C: \ test> _
Ancak, Microsoft'un araç zinciri oluştururken GUI alt sistemi olarak varsayılan olarak çalışmaz:
C: \ test> msvc x.cpp user32.lib / link / subsystem: windows x.cpp LIBCMT.lib (wincrt0.obj): hata LNK2019: __tmainCRTStartu işlevinde başvurulan çözümlenmemiş harici sembol _WinMain @ 16 p x.exe: önemli hata LNK1120: 1 çözülmemiş harici C: \ test> _
Teknik olarak bunun nedeni, Microsoft'un bağlayıcısının GUI alt sistemi için varsayılan olarak standart olmamasıdır . Varsayılan olarak, alt sistem GUI olduğunda, Microsoft'un bağlayıcısı bir çalışma zamanı kitaplığı giriş noktası kullanır ; bu, makine kodu yürütmenin başladığı ve winMainCRTStartup
standart WinMain
yerine Microsoft'un standart dışı çağrısı olarak adlandırılan işlevdir main
.
Yine de bunu düzeltmek için önemli bir şey yok.
Tek yapmanız gereken, Microsoft'un linker'ına hangi giriş noktasının kullanılacağını, yani mainCRTStartup
standardı çağıran main
:
C: \ test> msvc x.cpp user32.lib / link / subsystem: windows / entry: mainCRTStartup x.cpp C: \ test> dumpbin / başlıklar x.exe | / i "alt sistem" bul | bul / i "Windows" 2 alt sistem (Windows GUI) C: \ test> _
Sorun değil ama çok sıkıcı. Ve o kadar esrarengiz ve gizlidir ki, çoğunlukla yalnızca Microsoft'un standart olmayan varsayılan araçlarını kullanan çoğu Windows programcısı bunu bilmiyor ve yanlışlıkla bir Windows GUI alt sistemi programının standart WinMain
yerine standart dışı olması gerektiğini düşünüyor. main
. Geçerken, C ++ 0x ile Microsoft bununla ilgili bir sorun yaşayacaktır, çünkü derleyicinin bağımsız mı yoksa barındırılı mı olduğunu duyurması gerekir (barındırıldığında standardı desteklemesi gerekir main
).
Neyse, bu g ++ nedeni bu olabilir şikayet WinMain
Microsoft'un araçları GUI alt sistemi programları için varsayılan olarak gerektirdiğini saçma standart olmayan başlatma fonksiyonu var: Eksik.
Ancak yukarıda görebileceğiniz gibi, g ++ 'nın main
bir GUI alt sistem programı için bile standartla bir sorunu yoktur .
Peki sorun ne olabilir?
Eh, muhtemelen vardır eksik bir main
. Ve muhtemelen sende de (uygun) WinMain
yok! Ve sonra g ++, aradıktan sonra main
(böyle değil) ve Microsoft'un standart dışı WinMain
(böyle değil), ikincisinin eksik olduğunu bildirir.
Boş bir kaynakla test etme:
C: \ test> nul> y.cpp yazın C: \ test> gnuc y.cpp -mwindows c: / program files / mingw / bin /../ lib / gcc / mingw32 / 4.4.1 /../../../ libmingw32.a (main.o): main.c :(. metin + 0xd2 ): tanımsız referen ce `` WinMain @ 16 '' Collect2: ld 1 çıkış durumu döndürdü C: \ test> _
main
veya a tanımlayın veya WinMain
ilgili dosyanın projeye dahil edildiğinden emin olun. Şerefe,
main
ya winmain
? Teşekkürler
Yukarıdaki gönderiyi Cheers ve hth tarafından özetlemek gerekirse. - Alf, sahip olduğunuzdan main()
veya WinMain()
tanımladığınızdan emin olun ve g ++ doğru olanı yapmalıdır.
Benim sorunum, main()
kazara bir ad alanı içinde tanımlanmış olmasıydı.
Uygulamamı SDL ile derlerken bu hatayla karşılaşıyordum. Bunun nedeni, SDL'nin SDL_main.h'de kendi ana işlevini tanımlamasıydı. SDL'yi önlemek için ana işlevi tanımlayın, SDL.h başlığı dahil edilmeden önce bir SDL_MAIN_HANDLED makrosu tanımlanmalıdır.
Oluşturmadan önce .c dosyanızı kaydetmeyi deneyin. Bilgisayarınızın, içinde bilgi olmayan bir dosyaya giden yolu referans gösterdiğine inanıyorum.
--C projeleri oluştururken benzer bir sorun yaşandı
Tüm Dosyaların Projenize Dahil Edildiğini Kontrol Edin:
CLion'u güncelledikten sonra aynı hatayı aldım. Saatlerce uğraştıktan sonra, dosyalarımdan birinin proje hedefine dahil olmadığını fark ettim. Onu aktif projeye geri ekledikten sonra, winmain16 için tanımsız referansı almayı bıraktım ve kod derlendi.
Düzenleme: IDE'nizdeki yapı ayarlarını kontrol etmek de faydalı olacaktır.
(Bu hatanın yakın zamanda IDE'yi güncellemeyle ilgili olup olmadığından emin değilim - nedensel veya basitçe bağıntılı olabilir. Bu faktör hakkında herhangi bir fikirle yorum yapmaktan çekinmeyin!)
All you have to do is to tell Microsoft's linker which entry point to use, namely mainCRTStartup, which calls standard main
.Eclipse CDT
Komut satırını kullanmadığım için bunu yapmanın bir yolu var mı ? Teşekkürler