Come posso utilizzare correttamente SDL2 nei miei programmi?
Voglio creare un gioco usando SDL2, ma non riesco a compilare e / o eseguire il mio codice, per favore aiutatemi!
SDL2 è notoriamente difficile da configurare ed è spesso la prima libreria che aspiranti sviluppatori di giochi cercano di utilizzare.
Questo post è inteso come un duplicato canonico di problemi comuni con la configurazione di SDL2.
Risposte
Questa risposta riguarda MinGW / GCC e non Visual Studio.
Questa risposta si occupa principalmente di Windows. Le cose sono più facili su altri sistemi operativi, vedere la parte inferiore della risposta per un riepilogo.
Ho cercato di mantenere questa risposta estremamente semplice, in modo che anche un principiante possa usarla.
Errori comuni
Gli errori comuni che puoi ottenere sono:
SDL.h: No such file or directory(durante la compilazione)undefined reference tovarie funzioni (durante il collegamento).dllErrori misteriosi (durante l'esecuzione del programma).
Questo elenco è ordinato da cattivo a buono. Se cambi qualcosa e ottieni un errore diverso, usa questo elenco per sapere se hai migliorato o peggiorato le cose.
Vedi la risposta di seguito per come risolvere tutti questi problemi.
Il preambolo
Ecco alcune cose che voglio dirti prima di arrivare a correggere gli errori.
0. Non seguire cattivi consigli.
Alcune risorse ti suggeriranno di fare #define SDL_MAIN_HANDLEDo #undef main. Non farlo. Queste soluzioni si discostano dal modo in cui SDL2 deve essere utilizzato e con la giusta configurazione non sono MAI necessarie.
Alcuni sostengono che quelli siano migliori del modo previsto, ma suggerisco di imparare prima nel modo previsto, poi imparare qual è la differenza e poi prendere una decisione istruita.
1. Scopri come compilare direttamente dalla console, puoi iniziare a utilizzare un IDE in un secondo momento. Se stai usando un IDE, ti consiglio di assicurarti prima di essere in grado di compilare il tuo programma direttamente dalla console, per escludere qualsiasi problema di configurazione IDE. Dopo averlo capito, puoi usare le stesse opzioni del compilatore nel tuo IDE.
Suggerisco anche di evitare CMake se hai appena iniziato, per escludere eventuali problemi relativi a CMake. Puoi iniziare a usarlo più tardi.
2. Scarica i file SDL2 corretti . Assicurati di avere i file giusti. Hai bisogno dell'archivio chiamato SDL2-devel-2.0.x-mingw.tar.gzda qui .
Disimballalo in qualsiasi directory, preferibilmente da qualche parte vicino al tuo codice sorgente. La decompressione direttamente nella directory del compilatore è spesso considerata una cattiva pratica.
3. Conoscere la differenza tra flag del compilatore e flag del linker . Un "flag" è un'opzione specificata nella riga di comando durante la creazione del programma. Quando usi un singolo comando, ad esempio g++ foo.cpp -o foo.exe, tutte le tue bandiere vengono aggiunte nello stesso posto (a questo singolo comando).
Ma quando crei il tuo programma in due passaggi, ad esempio:
g++ foo.cpp -c -o foo.o(compilazione)g++ foo.o -o foo.exe(collegamento)
devi sapere a quale dei due comandi aggiungere un flag. I flag che devono essere aggiunti al primo comando sono "flag del compilatore" e i flag che devono essere aggiunti al secondo sono "flag del linker". Nella risposta seguente, quando ti dico di aggiungere un flag, specificherò se è un flag del compilatore o un flag del linker.
La maggior parte dei IDE richiederà di specificare compilatore ed il linker bandiere a parte, quindi, anche se si utilizza un unico comando ora , è bene sapere che la bandiera va dove.
Se non diversamente specificato, l'ordine dei flag non ha importanza.
SDL.h: No such file or directory
O eventuali errori simili relativi all'inclusione di SDL.ho SDL2/SDL.h.
Devi dire al tuo compilatore la directory in cui si SDL.htrova. È contenuto nei file SDL che hai scaricato (vedi preambolo).
Aggiungi quanto segue ai flag del tuo compilatore:, -Iseguito da una directory.
Esempio: -IC:/Users/HolyBlackCat/Downloads/SDL2-2.0.12/x86_64-w64-mingw32/include/SDL2. (Anche i percorsi relativi funzionano, ad es -ISDL2-2.0.12/x86_64-w64-mingw32/include/SDL2.)
Nota che il flag può essere diverso a seconda di come scrivi #include:
- Se lo fai
#include <SDL.h>, il percorso dovrebbe terminare con.../include/SDL2(come sopra). Questo è il modo consigliato. - Se lo fai
#include <SDL2/SDL.h>, il percorso dovrebbe terminare con.../include.
undefined reference to varie funzioni
Il messaggio di errore menzionerà varie SDL_...funzioni (spesso quelle che usi nel tuo programma) e / o WinMain. Se lo menziona SDL_main, consultare la sezione " undefined reference to SDL_mainsolo" di seguito.
È necessario aggiungere seguenti flag linker: -lmingw32 -lSDL2main -lSDL2. L'ordine è importante. I flag devono apparire DOPO ogni file .c/ .cpp/ .o.
La scrittura -lSDL2main -lSDL2indica al linker di utilizzare i file chiamati libSDL2main.a, libSDL2.a(o libSDL2.dll.a) inclusi nei file SDL che hai scaricato. Hai bisogno di un altro flag per dire al linker dove cercare quei .afile. Aggiungi quanto segue ai flag del tuo linker:, -Lseguito dalla directory.
Esempio: -LC:/Users/HolyBlackCat/Desktop/SDL2-2.0.12/x86_64-w64-mingw32/lib. (Anche i percorsi relativi funzionano, ad es -LSDL2-2.0.12/x86_64-w64-mingw32/lib.)
Ho aggiunto tutte quelle bandiere e non è cambiato nulla:
Se l'hai fatto e continui a ricevere gli stessi undefined referenceerrori, probabilmente usi i .afile SDL sbagliati . L'archivio scaricato contiene due serie di file: i686-w64-mingw32(32 bit) e x86_64-w64-mingw32(64 bit). È necessario utilizzare i file corrispondenti al compilatore, che può anche essere a 32 o 64 bit. Stampa (8*sizeof(void*))per vedere se il tuo compilatore è a 32 o 64 bit. Anche se pensi di utilizzare i file giusti, prova gli altri per essere sicuro.
Alcune delle versioni MinGW possono essere commutate tra le modalità a 32 bit e 64 bit utilizzando i flag -m32e -m64(quelli probabilmente devono essere aggiunti sia ai flag del compilatore che del linker). Puoi provare anche quelli.
Arrivo undefined referencea una funzione specifica:
• undefined reference to WinMainsolo
Ci sono tre possibilità, tutte trattate nella sezione precedente:
- Hai dimenticato la
-lSDL2mainbandiera. - Il
libSDL2main.afile che usi non corrisponde al tuo compilatore (file a 32 bit con un compilatore a 64 bit o viceversa). - Metti il
-lSDL2mainflag a sinistra di alcuni file.c/.cpp/.o. Deve sempre essere a destra.
Cerca di evitare #define SDL_MAIN_HANDLEDo #undef mainquando risolvi questo problema, vedi il preambolo per la spiegazione.
• undefined reference to SDL_mainsolo
Devi avere una mainfunzione. La tua mainfunzione deve assomigliare int main(int, char **). NON int main() e NON void main() . Questa è una delle stranezze di SDL2.
È consentito aggiungere qualsiasi nome di parametro, ad es int main(int argc, char **argv). Anche il secondo parametro può essere scritto come char *[]o con un nome: char *argv[]. Non sono consentite altre modifiche.
Cerca di evitare #define SDL_MAIN_HANDLEDo #undef mainquando risolvi questo problema, vedi il preambolo per la spiegazione.
.dllerrori correlati
Hai creato con successo un .exe, ma non puoi eseguirlo a causa di misteriosi errori che ne citano alcuni .dll. Ci sei quasi!
Il che .exehai fatto ha bisogno di alcuni .dlls per funzionare. Se non li trova, te lo dirà e si rifiuterà di scappare. Questo è facile. Può anche trovare versioni sbagliate di loro lasciate da altri programmi che hai installato, quindi otterrai alcuni errori molto criptici.
Il programma cercherà i messaggi .dlldi posta elettronica in posizioni diverse, ma la soluzione più affidabile è metterli nella stessa directory del file .exe. Questa directory viene cercata per prima, quindi altre versioni di .dlls che potresti avere altrove non interferiranno.
Devi capire di quali .dllprogrammi ha bisogno il tuo programma e metterli nella directory dove si .exetrova il tuo (ad eccezione dei sistemi .dll, che non hai bisogno di copiare).
Esistono due tipi di errori che puoi ottenere:
Un errore che ti dice solo cosa
.dllmanca.SDL2.dllmanca. - È contenuto nei file SDL che hai scaricato.Tieni presente che i file contengono due diversi messaggi di posta
SDL2.dllelettronica: uno a 32 bit (nellai686-w64-mingw32directory) e uno a 64 bit (inx86_64-w64-mingw32). Prendi quello giusto, se necessario prova entrambi.Qualche altro
.dllmanca. - Viene fornito con il compilatore. Cerca nella directory in cui sigcc.exetrova il tuo .Se ne copi uno
.dlle ne chiede di più, è normale, potresti dover ripetere l'operazione ~ 3 volte.
Un
.dllerrore criptico . - Il tuo programma ha trovato una versione sbagliata di da.dllqualche parte nel tuo sistema.È necessario copiare tutti i messaggi non di sistema
.dllnecessari nella directory in cui si.exetrova.Per prima cosa, copia
SDL2.dll(vedi la sezione "SDL2.dllmanca" sopra per sapere dove trovarlo).Quindi, copia i seguenti messaggi
.dlldalla directory del compilatore (la directory in cuigcc.exesi trova):libgcc_s_seh-1.dll(il nome può variare a seconda della versione MinGW, ma inizierà sempre conlibgcc)libstdc++-6.dll(solo per C ++, salta se stai scrivendo in C)libwinpthread-1.dll(il nome può variare a seconda della versione MinGW, ma verrà sempre menzionatothread; alcune versioni non lo usano affatto)
Questo dovrebbe correggere tutti i tuoi errori. Se vuoi saperne di più o non ti è stato d'aiuto:
Maggiori informazioni sulla .dlls
È possibile creare un messaggio .exeche non dipenda da nessuno (non di sistema) .dllutilizzando il -staticflag del linker, questo è chiamato "collegamento statico". Questo viene fatto raramente e non dovresti aver bisogno di farlo se hai eseguito correttamente i passaggi precedenti. Ciò richiede flag del linker diversi dal solito (circa 20), vedere il sdl2.pcfile fornito con SDL per i flag esatti (sono nella Libs.privatesezione).
Nella sezione precedente ti ho detto da cosa .dlldipende il tuo programma. Come lo sapevo? Esistono diversi modi per capirlo da soli:
Il modo grezzo:
Apri la console,
cdnella directory in cui ti.exetrovi, quindi digitaset PATH=(non preoccuparti, questo non cambia lePATHimpostazioni di sistema e influisce solo sulla sessione corrente della console).Rimuovi tutti
.dlli messaggi che potresti aver già copiato lì.Ora, se esegui
.exeda questa console, sarà in grado di trovare solo i sistemi.dll. Cercherà quelli non di sistema solo nella directory corrente (che non ne ha). Ora riceverai messaggi di errore chiari che dicono cosa.dllsono necessari e puoi copiarli uno per uno finché non inizia a funzionare. In questo modo conoscerai tutti i non di sistema.dllutilizzati dal tuo programma.Nota che questo metodo non è completamente infallibile.
C:\Windowse alcune delle directory annidate vengono sempre cercate, anche in questo caso. Normalmente non importa se gli unici.dllpresenti sono quelli di sistema, ma se qualche programma di installazione scadente ha copiato un custom.dlllì dentro, allora questo metodo non funzionerà correttamente.È una buona idea cercare tra
C:\Windowsle directory annidate per.dlli messaggi di posta elettronica che non dovrebbero essere presenti ed eliminarli. CercaSDL2.dlle per qualsiasi messaggio.dllfornito con il tuo compilatore (nella directory in cui sigcc.exetrova).Il modo civilizzato:
Usa uno strumento come Dependency Walker o
ntldd. Dovrai esaminare il loro output e determinare se ognuno.dllè di sistema o non di sistema. Se a.dllviene fornito con il compilatore o appartiene a una libreria che usi (SDL2.dll), allora non è di sistema. Tutti i messaggi rimanenti.dllsono di sistema, ignorali.
Altri problemi
D: Il mio programma apre sempre una finestra della console quando lo eseguo, oltre a tutte le finestre che apro utilizzando SDL. Come me ne sbarazzo?
- A: Aggiungi
-mwindowsai flag del linker.
- A: Aggiungi
D: Il mio programma ha l'icona del file predefinita , ma ne voglio uno personalizzato.
A: La tua icona deve essere nel
.icoformato. Crea un file con.rcestensione (diciamoicon.rc), digita quanto segue:MAINICON ICON "icon.ico"(la prima parte è un nome arbitrario, puoi cambiarlo; la seconda parte deve essere sempreICON, la terza parte è il percorso dell'icona). Converti il file in un.ousingwindres -i icon.rc -o icon.o(ilwindresprogramma viene fornito con il compilatore). Specificare il.ofile risultante durante il collegamento, ad esg++ foo.cpp icon.o -o foo.exe.Le versioni recenti di SDL2 hanno una bella proprietà di utilizzare la stessa icona dell'icona della finestra, quindi non è necessario utilizzarla
SDL_SetWindowIcon.
D: Ottengo un errore
'SDL_VideoMode' wasn't declared in this scope.- R:
SDL_VideoModeesisteva in SDL1.2, ma non fa parte di SDL2. Il codice è stato scritto per l'obsoleto SDL1.2. Trova un tutorial migliore che si occupi del nuovo SDL2.
- R:
Non sono su Windows, cosa devo fare di diverso?
L'intera risposta sopra è rivolta principalmente a MinGW e Windows. Se non sei su Windows, le cose diventano più facili:
Nessun
.dllproblema correlato.Non è necessario scaricare manualmente SDL2, dovrebbe essere nel tuo gestore di pacchetti.
Non c'è bisogno di pensare a quale compilatore o linker flag usare:
pkg-config --cflags sdl2ti dirà i flag del compilatore.pkg-config --libs sdl2ti dirà i flag del linker. Aggiungi--staticse vuoi flag per il collegamento statico.
Non è necessario
-lSDL2maine non ci sono problemi relativi aSDL_main.
D'altra parte:
Distribuire i tuoi programmi ad altre persone diventa più difficile, non puoi semplicemente spedire un gruppo di messaggi
.dllcon il tuo programma.Il processo di impostazione di un'icona personalizzata è diverso.
Approccio alternativo: usa un ambiente simile a Linux su Windows
La parte della sezione precedente sull'installazione delle librerie e sulla determinazione automatica dei flag del compilatore suona conveniente? Puoi averlo anche su Windows.
Scarica MSYS2. Avrai un gestore di pacchetti (da cui puoi installare SDL), compilatori aggiornati e una serie di utilità comuni portate da Linux (incluso pkg-config). Questo risolve la maggior parte dei problemi specifici di Windows.
Su Mac questo è quello che seguo per XCode (deve installare g ++):
collegamento sdl:
g++ main.cpp -o main $(sdl2-config --cflags --libs)
Fasi del progetto XCODE:
apri l'app terminale (macOS)
COSTRUISCI IMPOSTAZIONI (seleziona "tutto" e nella barra di ricerca "combinata" inserisci: "cerca")
fare clic su "percorsi di ricerca dell'intestazione (facendo clic con il lato destro)
Inserisci:
/usr/local/includeFASI DI COSTRUZIONE -> COLLEGA BIBLIOTECHE BINARIE (fai clic su più)
digita
SDL-> fai clic su "aggiungi altro"premere: command+ SHIFT+ g(per portare la barra di ricerca)
digitare:
usr/local/Cellarvai a: SDL2 -> 2.0.8 -> lib -> libSDL2-2.2.0.dylib (assicurati che non sia un collegamento)
Una soluzione per Visual Studio:
Perché non utilizzare un gestore di pacchetti? Uso vcpkg e semplifica l' utilizzo di librerie di terze parti. Prendi il sorgente vcpkg ed estrailo in un posto sicuro, come C:/, quindi esegui il suo script di bootstrap bootstrap-vcpkg.bat, questo genererà un vcpkgeseguibile. Quindi esegui vcpkg integrate installper rendere disponibili le librerie installate con vcpkg in Visual Studio.
Cerca la libreria di cui hai bisogno:
vcpkg search sdl
imgui[sdl2-binding] Make available SDL2 binding
libwebp[vwebp-sdl] Build the vwebp viewer tool.
magnum[sdl2application] Sdl2Application library
sdl1 1.2.15#12 Simple DirectMedia Layer is a cross-platform development library designed to p...
sdl1-net 1.2.8-3 Networking library for SDL
sdl2 2.0.12-1 Simple DirectMedia Layer is a cross-platform
...
Installarlo con: vcpkg install sdl2.
Ora devi solo includere le intestazioni SDL2 e tutto funzionerà immediatamente. La libreria verrà collegata automaticamente.
Puoi saperne di più su vcpkg qui .