¿Cómo utilizo SDL2 en mis programas correctamente?
Quiero hacer un juego usando SDL2, pero no puedo compilar y / o ejecutar mi código, ¡ayuda!
SDL2 es notoriamente difícil de configurar y, a menudo, es la primera biblioteca que los aspirantes a desarrolladores de juegos intentan utilizar.
Esta publicación está pensada como un duplicado canónico para problemas comunes con la configuración de SDL2.
Respuestas
Esta respuesta trata con MinGW / GCC, y no con Visual Studio.
Esta respuesta se ocupa principalmente de Windows. Las cosas son más fáciles en otros sistemas operativos, consulte la parte inferior de la respuesta para obtener un resumen.
Intenté mantener esta respuesta muy simple, para que incluso un novato pueda usarla.
Errores comunes
Los errores comunes que puede obtener son:
SDL.h: No such file or directory(al compilar)undefined reference tovarias funciones (al vincular).dllErrores misteriosos relacionados (al ejecutar su programa).
Esta lista está ordenada de mala a buena. Si cambia algo y obtiene un error diferente, use esta lista para saber si ha mejorado o empeorado las cosas.
Consulte la respuesta a continuación para saber cómo solucionarlos todos.
El preámbulo
Aquí hay algunas cosas que quiero decirles antes de que arreglemos los errores.
0. No sigas los malos consejos.
Algunos recursos le sugerirán que haga #define SDL_MAIN_HANDLEDo #undef main. No hagas eso. Esas soluciones se desvían de la forma en que se diseñó SDL2 y, con la configuración correcta, NUNCA son necesarias.
Algunos argumentan que son mejores que la forma prevista, pero sugiero aprender primero la forma prevista, luego saber cuál es la diferencia y luego tomar una decisión informada.
1. Descubra cómo compilar directamente desde la consola, puede comenzar a usar un IDE más tarde. Si está utilizando un IDE, le sugiero que primero se asegure de que puede compilar su programa directamente desde la consola, para descartar cualquier problema de configuración del IDE. Después de darse cuenta de eso, puede usar las mismas opciones del compilador en su IDE.
También sugiero evitar CMake si acaba de empezar, para descartar cualquier problema relacionado con CMake. Puedes empezar a usarlo más tarde.
2. Descargue los archivos SDL2 correctos . Asegúrese de tener los archivos correctos. Necesita el archivo llamado SDL2-devel-2.0.x-mingw.tar.gzdesde aquí .
Descomprímalo en cualquier directorio, preferiblemente en algún lugar cerca de su código fuente. Descomprimir directamente en el directorio del compilador a menudo se considera una mala práctica.
3. Conozca la diferencia entre los indicadores del compilador y los indicadores del enlazador . Una "bandera" es una opción que especificas en la línea de comando al construir tu programa. Cuando usa un solo comando, como g++ foo.cpp -o foo.exe, todas sus banderas se agregan en el mismo lugar (a este solo comando).
Pero cuando construye su programa en dos pasos, por ejemplo:
g++ foo.cpp -c -o foo.o(compilando)g++ foo.o -o foo.exe(enlace)
tienes que saber a cuál de los dos comandos agregar una bandera. Los indicadores que deben agregarse al primer comando son "indicadores del compilador" y los indicadores que deben agregarse al segundo son "indicadores del enlazador". En la respuesta a continuación, cuando le pida que agregue un indicador, especificaré si es un indicador del compilador o un indicador del enlazador.
La mayoría de los IDE requerirán que especifique los indicadores del compilador y del vinculador por separado, por lo que incluso si usa un solo comando ahora , es bueno saber qué indicador va a dónde.
A menos que se especifique lo contrario, el orden de las banderas no importa.
SDL.h: No such file or directory
O cualquier error similar relacionado con la inclusión de SDL.ho SDL2/SDL.h.
Necesita decirle a su compilador el directorio donde SDL.hestá. Está en los archivos SDL que ha descargado (consulte el preámbulo).
Agregue lo siguiente a las banderas de su compilador:, -Iseguido de un directorio.
Ejemplo: -IC:/Users/HolyBlackCat/Downloads/SDL2-2.0.12/x86_64-w64-mingw32/include/SDL2. (Las rutas relativas también funcionan, p -ISDL2-2.0.12/x86_64-w64-mingw32/include/SDL2. Ej .)
Tenga en cuenta que la bandera puede ser diferente dependiendo de cómo escriba #include:
- Si lo hace
#include <SDL.h>, entonces la ruta debería terminar con.../include/SDL2(como arriba). Esta es la forma recomendada. - Si es así
#include <SDL2/SDL.h>, la ruta debería terminar en.../include.
undefined reference to Varias funciones
El mensaje de error mencionará varias SDL_...funciones (a menudo las que usa en su programa) y / o WinMain. Si menciona SDL_main, consulte el apartado " undefined reference to SDL_mainsolo" a continuación.
Es necesario añadir siguientes banderas enlazador: -lmingw32 -lSDL2main -lSDL2. El orden importa. Las banderas deben aparecer DESPUÉS de cualquier archivo .c/ .cpp/ .o.
La escritura -lSDL2main -lSDL2le dice al vinculador que use archivos llamados libSDL2main.a, libSDL2.a(o libSDL2.dll.a) que están incluidos en los archivos SDL que descargó. Necesita una bandera más para decirle al vinculador dónde buscar esos .aarchivos. Agregue lo siguiente a sus banderas del vinculador:, -Lseguido del directorio.
Ejemplo: -LC:/Users/HolyBlackCat/Desktop/SDL2-2.0.12/x86_64-w64-mingw32/lib. (Las rutas relativas también funcionan, p -LSDL2-2.0.12/x86_64-w64-mingw32/lib. Ej .)
Agregué todas esas banderas y nada cambió:
Si hizo eso y aún obtiene los mismos undefined referenceerrores, probablemente use los .aarchivos SDL incorrectos . El archivo que descargó contiene dos conjuntos de archivos: i686-w64-mingw32(32 bits) y x86_64-w64-mingw32(64 bits). Debe utilizar los archivos que coincidan con su compilador, que también pueden ser de 32 bits o de 64 bits. Imprima (8*sizeof(void*))para ver si su compilador es de 32 bits o de 64 bits. Incluso si cree que usa los archivos correctos, pruebe los otros para estar seguro.
Algunas de las versiones de MinGW se pueden cambiar entre los modos de 32 bits y 64 bits utilizando los indicadores -m32y -m64(probablemente estos deban agregarse tanto al compilador como al vinculador). Puedes probarlos también.
Llego undefined referencea una función específica:
• undefined reference to WinMainsolo
Hay tres posibilidades, todas las cuales se trataron en la sección anterior:
- Olvidaste la
-lSDL2mainbandera. - El
libSDL2main.aarchivo que usa no coincide con su compilador (archivo de 32 bits con un compilador de 64 bits, o viceversa). - Pones la
-lSDL2mainbandera a la izquierda de algunos archivos.c/.cpp/.o. Siempre debe estar a la derecha.
Intente evitar #define SDL_MAIN_HANDLEDo #undef mainal resolver este problema, consulte el preámbulo para obtener una explicación.
• undefined reference to SDL_mainsolo
Necesitas tener una mainfunción. Tu mainfunción debe verse así int main(int, char **). NO int main() y NO void main() . Esta es una de las peculiaridades de SDL2.
Se permite agregar cualquier nombre de parámetro, por ejemplo int main(int argc, char **argv). También el segundo parámetro se puede escribir como char *[]o con un nombre: char *argv[]. No se permiten otros cambios.
Intente evitar #define SDL_MAIN_HANDLEDo #undef mainal resolver este problema, consulte el preámbulo para obtener una explicación.
.dll-errores relacionados
Ha creado correctamente una .exe, pero no puede ejecutarla debido a misteriosos errores que mencionan algunos .dlls. ¡Ya casi estás ahí!
El .exeque hiciste necesita algunos .dlls para ejecutarse. Si no los encuentra, se lo dirá y se negará a correr. Esto es facil. También puede encontrar versiones incorrectas de otros programas que haya instalado, luego obtendrá algunos errores muy crípticos.
Su programa buscará los .dlls en diferentes ubicaciones, pero la solución más confiable es ponerlos en el mismo directorio que .exe. Este directorio se busca primero, por lo que otras versiones de los .dllmensajes de correo electrónico que pueda tener en otro lugar no interferirán.
Necesita averiguar cuál .dlles su programa y colocarlo en el directorio donde .exeestá (excepto los del sistema .dll, que no necesita copiar).
Hay dos tipos de errores que puede obtener:
Un error que solo te dice lo que
.dllfalta.SDL2.dllEstá perdido. - Está en los archivos SDL que ha descargado.Tenga en cuenta que los archivos contienen dos correos electrónicos diferentes
SDL2.dll: uno de 32 bits (en eli686-w64-mingw32directorio) y uno de 64 bits (enx86_64-w64-mingw32). Obtenga el correcto, si es necesario, pruebe ambos..dllFalta alguna otra . - Se envía con su compilador. Busque en el directorio dondegcc.exeestá su .Si copia uno
.dlly solicita más, es normal, es posible que deba repetir esto ~ 3 veces.
Un
.dllerror críptico relacionado. - Su programa encontró una versión incorrecta de en.dllalgún lugar de su sistema.Debe copiar todos los mensajes de correo electrónico que no sean del sistema
.dllque necesite en el directorio donde se.exeencuentra.Primero, copie
SDL2.dll(vea la sección "SDL2.dllfalta" arriba para saber dónde encontrarlo).Luego, copie los siguientes correos
.dllelectrónicos de su directorio del compilador (el directorio dondegcc.exese encuentra):libgcc_s_seh-1.dll(el nombre puede variar según su versión de MinGW, pero siempre comenzará conlibgcc)libstdc++-6.dll(solo para C ++, omita si está escribiendo en C)libwinpthread-1.dll(el nombre puede variar según su versión de MinGW, pero siempre lo mencionaráthread; algunas versiones no usan esto en absoluto)
Eso debería arreglar todos tus errores. Si desea saber más o no ayudó:
Más información sobre el .dlls
Es posible hacer un .exeque no dependa de ningún (que no sea del sistema) .dllmediante el uso de la -staticbandera del enlazador, esto se llama "enlace estático". Esto rara vez se hace y no debería necesitar hacerlo si siguió los pasos anteriores correctamente. Esto requiere diferentes indicadores del enlazador de lo habitual (alrededor de 20 de ellos), consulte el sdl2.pcarchivo enviado con SDL para conocer los indicadores exactos (se encuentran en la Libs.privatesección).
En la sección anterior te dije de qué .dlldepende tu programa. ¿Cómo lo supe? Hay varias formas de averiguarlo usted mismo:
El camino crudo:
Abra la consola,
cden el directorio donde.exeestá, luego escribaset PATH=(no se preocupe, esto no cambia laPATHconfiguración de su sistema y solo afecta la sesión actual de la consola).Elimine todos los mensajes de correo
.dllelectrónico que ya haya copiado allí.Ahora, si ejecuta el
.exedesde esta consola, solo podrá encontrar el.dlls del sistema . Buscará los que no sean del sistema solo en el directorio actual (que no tiene ninguno). Ahora obtendrá mensajes de error claros que indican qué correos electrónicos.dllson necesarios y podrá copiarlos uno por uno hasta que comience a funcionar. De esta manera sabrá todos los que no son del sistema.dllque utiliza su programa.Tenga en cuenta que este método no es completamente infalible.
C:\Windowsy siempre se busca en algunos de los directorios anidados, incluso en este caso. Normalmente, no importa si los únicos.dllcorreos electrónicos son los del sistema, pero si algún instalador de mala calidad copió un archivo personalizado.dll, este método no funcionará correctamente.Es una buena idea buscar en los
C:\Windowsdirectorios anidados los correos.dllelectrónicos que no deberían estar allí y eliminarlos. BusqueSDL2.dlly busque cualquier.dllcorreo electrónico que también se envíe con su compilador (en el directorio dondegcc.exeestá).El camino civilizado:
Utilice una herramienta como Dependency Walker o
ntldd. Tendrá que revisar su salida y determinar si cada uno.dlles un sistema o no. Si.dllse envía con su compilador o pertenece a una biblioteca que usa (SDL2.dll), entonces no es del sistema. Los restantes.dllson del sistema, ignórelos.
Otros problemas
P: Mi programa siempre abre una ventana de consola cuando lo ejecuto, además de cualquier ventana que abra con SDL. ¿Como me deshago de esto?
- R: Agregar
-mwindowsa las banderas del vinculador.
- R: Agregar
P: Mi programa tiene el icono de archivo predeterminado , pero quiero uno personalizado.
R: Su icono debe tener el
.icoformato. Cree un archivo con.rcextensión (digamosicon.rc), escriba lo siguiente en él:MAINICON ICON "icon.ico"(la primera parte es un nombre arbitrario, puede cambiarlo; la segunda parte siempre debe serICON, la tercera parte es la ruta al icono). Convierta el archivo a un.ousowindres -i icon.rc -o icon.o(elwindresprograma se envía con su compilador). Especifique el.oarchivo resultante al vincular, por ejemplog++ foo.cpp icon.o -o foo.exe.Las versiones recientes de SDL2 tienen la buena propiedad de usar el mismo ícono que el ícono de la ventana, por lo que no tiene que usarlo
SDL_SetWindowIcon.
P: Recibo un error
'SDL_VideoMode' wasn't declared in this scope.- R:
SDL_VideoModeexistía en SDL1.2, pero no forma parte de SDL2. Su código fue escrito para el SDL1.2 desactualizado. Encuentre un tutorial mejor que trate sobre el nuevo SDL2.
- R:
No estoy en Windows, ¿qué hago de manera diferente?
Toda la respuesta anterior está dirigida principalmente a MinGW y Windows. Si no está en Windows, las cosas se vuelven más fáciles:
No hay
.dllproblemas relacionados.No es necesario descargar SDL2 manualmente, debería estar en su administrador de paquetes.
No es necesario pensar en qué indicadores de compilador o vinculador usar:
pkg-config --cflags sdl2le dirá las banderas del compilador.pkg-config --libs sdl2le dirá las banderas del enlazador. Agregue--staticsi quiere banderas para enlaces estáticos.
No es necesario
-lSDL2mainy no hay problemas relacionados conSDL_main.
Por otra parte:
Distribuir sus programas a otras personas se vuelve más difícil, no puede simplemente enviar un montón de correos
.dllelectrónicos con su programa.El proceso de configuración de un icono personalizado es diferente.
Enfoque alternativo: use un entorno similar a Linux en Windows
¿Suena conveniente la parte de la sección anterior sobre la instalación de bibliotecas y la determinación de los indicadores del compilador? También puedes tener eso en Windows.
Descarga MSYS2. Tendrá un administrador de paquetes (desde el cual puede instalar SDL), compiladores actualizados y un conjunto de utilidades comunes portadas desde Linux (incluidas pkg-config). Esto resuelve la mayoría de los problemas específicos de Windows.
En Mac, esto es lo que sigo para XCode (debe instalar g ++):
vinculación sdl:
g++ main.cpp -o main $(sdl2-config --cflags --libs)
Pasos del proyecto XCODE:
aplicación de terminal abierta (macOS)
CONSTRUYE AJUSTES (seleccione 'todos' y la barra de búsqueda 'combinada' ingrese: "buscar")
haga clic en "rutas de búsqueda del encabezado (haga clic en el lado derecho)
añadir:
/usr/local/includeCONSTRUIR FASES -> ENLACE BIBLIOTECAS BINARIAS (haga clic en el signo más)
escriba
SDL-> haga clic en "agregar otro"presione: command+ SHIFT+ g(para traer la barra de búsqueda)
escribir:
usr/local/Cellarnavegue a: SDL2 -> 2.0.8 -> lib -> libSDL2-2.2.0.dylib (asegúrese de que no sea un atajo)
Una solución para Visual Studio:
¿Por qué no utilizar un administrador de paquetes? Utilizo vcpkg y hace que sea muy fácil consumir bibliotecas de terceros. Tome la fuente vcpkg y extráigala a un lugar seguro, como C:/, luego ejecute su script de arranque bootstrap-vcpkg.bat, esto generará un vcpkgejecutable. Luego, ejecútelo vcpkg integrate installpara que las bibliotecas instaladas con vcpkg estén disponibles en Visual Studio.
Busque la biblioteca que necesita:
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
...
Instalarlo con: vcpkg install sdl2.
Ahora solo necesita incluir encabezados SDL2, y todo funcionará de inmediato. La biblioteca se vinculará automáticamente.
Puede obtener más información sobre vcpkg aquí .