¿Alguien podría explicar qué
__imp__fprintf
y
__imp____iob_func
medios externos no resueltos?
Porque obtengo estos errores cuando intento compilar:
1>SDL2main.lib(SDL_windows_main.obj) : error LNK2019: unresolved external symbol __imp__fprintf referenced in function _ShowError
1>SDL2main.lib(SDL_windows_main.obj) : error LNK2019: unresolved external symbol __imp____iob_func referenced in function _ShowError
1>E:\Documents\Visual Studio 2015\Projects\SDL2_Test\Debug\SDL2_Test.exe : fatal error LNK1120: 2 unresolved externals
Ya puedo decir que el problema no es de vincular mal. He vinculado todo correctamente, pero por alguna razón no se compilará.
Estoy intentando utilizar SDL2.
Estoy usando Visual Studio 2015 como compilador.
Me he vinculado a SDL2.lib y SDL2main.lib en Linker -> Entrada -> Dependencias adicionales y me he asegurado de que los directorios de VC ++ sean correctos.
c++
sdl-2
visual-studio-2015
unresolved-external
RockFrenzy
fuente
fuente
Respuestas:
¡Finalmente he descubierto por qué está sucediendo esto!
En visual studio 2015, stdin, stderr, stdout se definen de la siguiente manera:
Pero anteriormente, se definieron como:
Así que ahora __iob_func ya no está definido, lo que conduce a un error de enlace cuando se usa un archivo .lib compilado con versiones anteriores de Visual Studio.
Para resolver el problema, puede intentar definir
__iob_func()
usted mismo cuál debería devolver una matriz que contenga{*stdin,*stdout,*stderr}
.Con respecto a los otros errores de enlace sobre las funciones de stdio (en mi caso lo fue
sprintf()
), puede agregar legacy_stdio_definitions.lib a sus opciones de vinculador.fuente
extern "C"
en la declaración / definición.extern "C" { FILE __iob_func[3] = { *stdin,*stdout,*stderr }; }
Para Milan Babuškov, en mi opinión, así es exactamente como debería verse la función de reemplazo :-)
fuente
#if defined(_MSC_VER) && (_MSC_VER >= 1900)
.Microsoft tiene una nota especial sobre esto ( https://msdn.microsoft.com/en-us/library/bb531344.aspx#BK_CRT ):
fuente
#pragma comment(lib, "legacy_stdio_definitions.lib")
, pero esto no soluciona el problema__imp___iob_func
, ¿hay una biblioteca heredada para esto también?Como se respondió anteriormente, la respuesta correcta es compilar todo con VS2015, pero por interés, el siguiente es mi análisis del problema.
Este símbolo no parece estar definido en ninguna biblioteca estática proporcionada por Microsoft como parte de VS2015, lo cual es bastante peculiar ya que todos los demás lo son. Para descubrir por qué, necesitamos mirar la declaración de esa función y, lo que es más importante, cómo se usa.
Aquí hay un fragmento de los encabezados de Visual Studio 2008:
Así que podemos ver que el trabajo de la función es devolver el inicio de una matriz de objetos FILE (no identificadores, el "FILE *" es el identificador, FILE es la estructura de datos opaca subyacente que almacena las ventajas importantes del estado). Los usuarios de esta función son las tres macros stdin, stdout y stderr que se utilizan para varias llamadas de estilo fscanf, fprintf.
Ahora echemos un vistazo a cómo Visual Studio 2015 define las mismas cosas:
Entonces, el enfoque ha cambiado para que la función de reemplazo ahora devuelva el identificador del archivo en lugar de la dirección de la matriz de objetos de archivo, y las macros han cambiado para simplemente llamar a la función pasando un número de identificación.
Entonces, ¿por qué no podemos proporcionar una API compatible? Hay dos reglas clave que Microsoft no puede contravenir en términos de su implementación original a través de __iob_func:
Cualquier cambio en cualquiera de los anteriores significaría que el código compilado existente vinculado con eso saldría muy mal si se llama a esa API.
Echemos un vistazo a cómo se definió FILE.
Primero, la definición de ARCHIVO VS2008:
Y ahora la definición de ARCHIVO VS2015:
Así que ahí está el quid de la cuestión: la estructura ha cambiado de forma. El código compilado existente que hace referencia a __iob_func se basa en el hecho de que los datos devueltos son tanto una matriz que se puede indexar como que en esa matriz los elementos están separados por la misma distancia.
Las posibles soluciones mencionadas en las respuestas anteriores a lo largo de estas líneas no funcionarían (si se llaman) por algunas razones:
La matriz FILE _iob se compilaría con VS2015 y, por lo tanto, se presentaría como un bloque de estructuras que contiene un vacío *. Suponiendo una alineación de 32 bits, estos elementos estarían separados por 4 bytes. Entonces _iob [0] está en el desplazamiento 0, _iob [1] está en el desplazamiento 4 y _iob [2] está en el desplazamiento 8. En cambio, el código de llamada esperará que FILE sea mucho más largo, alineado a 32 bytes en mi sistema, y así tomará la dirección de la matriz devuelta y agregará 0 bytes para llegar al elemento cero (ese está bien), pero para _iob [1] deducirá que necesita agregar 32 bytes y para _iob [2] deducirá que necesita agregar 64 bytes (porque así es como se veía en los encabezados VS2008). Y de hecho, el código desmontado de VS2008 lo demuestra.
Un problema secundario con la solución anterior es que copia el contenido de la estructura FILE (* stdin), no el identificador FILE *. Por lo tanto, cualquier código VS2008 buscaría una estructura subyacente diferente a VS2015. Esto podría funcionar si la estructura solo contuviera punteros, pero eso es un gran riesgo. En cualquier caso, la primera cuestión hace que esto sea irrelevante.
El único truco que he podido soñar es uno en el que __iob_func recorre la pila de llamadas para averiguar qué identificador de archivo real están buscando (según el desplazamiento agregado a la dirección devuelta) y devuelve un valor calculado tal que da la respuesta correcta. Esto es tan loco como parece, pero el prototipo solo para x86 (no x64) se enumera a continuación para su diversión. Funcionó bien en mis experimentos, pero su kilometraje puede variar, ¡no se recomienda para uso en producción!
fuente
Tuve el mismo problema en VS2015. Lo resolví compilando las fuentes SDL2 en VS2015.
fuente
SDL2main
y copiarSDL2main.lib
No se porque pero:
Después de la inclusión, pero antes de su principal, debería solucionarlo según mi experiencia.
fuente
Una solución más reciente a este problema: use las bibliotecas sdl más recientes en
" https://buildbot.libsdl.org/sdl-builds/sdl-visualstudio/?C=M;O=D "
Parece que han solucionado el problema, aunque es solo la biblioteca de 32 bits (creo).
fuente
Vincular significa no funcionar correctamente. Profundizando en stdio.h de VS2012 y VS2015, lo siguiente funcionó para mí. Por desgracia, tienes que decidir si debería funcionar para uno de {stdin, stdout, stderr}, nunca más de uno.
fuente
Mi consejo es no (intentar) implementar __iob_func.
Mientras corrige estos errores:
libpngd.v110.lib(pngrutil.obj) : error LNK2001: unresolved external symbol ___iob_func curllib.v110.lib(mprintf.obj) : error LNK2001: unresolved external symbol ___iob_func
Probé las soluciones de las otras respuestas, pero al final, devolver una
FILE*
matriz C no coincide con una matriz de estructuras IOB internas de Windows. @Volker tiene razón en que nunca funcionará para más de uno destdin
,stdout
ostderr
.Si una biblioteca UTILIZA uno de esos flujos, se bloqueará . Siempre que su programa no haga que lib los use, nunca lo sabrá . Por ejemplo,
png_default_error
escribe enstderr
cuando el CRC no coincide en los metadatos del PNG. (Normalmente no es un problema digno de un accidente)Conclusión: No es posible mezclar las bibliotecas VS2012 (Platform Toolset v110 / v110_xp) y VS2015 +, si usan stdin, stdout y / o stderr.
Solución: vuelva a compilar sus bibliotecas que tienen
__iob_func
símbolos sin resolver con su versión actual de VS y un conjunto de herramientas de plataforma correspondiente.fuente
Utilice SDL2main.lib y SDL.lib precompilados para la biblioteca de su proyecto VS2015: https://buildbot.libsdl.org/sdl-builds/sdl-visualstudio/sdl-visualstudio-2225.zip
fuente
Resuelvo este problema con la siguiente función. Yo uso Visual Studio 2019.
debido a que la llamada a la función definida por macro stdin, la expresión "* stdin" no se puede utilizar como inicializador de matriz global. Pero el inicializador de matriz local es posible. lo siento, soy pobre en inglés.
fuente
Para cualquiera que todavía esté buscando una respuesta donde los trucos anteriores no funcionaron. La vinculación estática es la forma de resolver este problema. Cambie la configuración de la biblioteca en tiempo de ejecución como se muestra a continuación
Project properties --> C/C++ --> Code generation --> Runtime Library --> Multi-threaded Debug (/MTd) instead of /MDd
fuente
Me las arreglé para solucionar el problema.
La fuente del error fue esta línea de código, que se puede encontrar en el código fuente de SDLmain.
Entonces, lo que hice fue editar el código fuente en SDLmain de esa línea también:
Y luego construí SDLmain y copié y reemplacé el antiguo SDLmain.lib en mi directorio de biblioteca SDL2 con el recién construido y editado.
Luego, cuando ejecuté mi programa con SDL2, no aparecieron mensajes de error y el código se ejecutó sin problemas.
No sé si esto me morderá más tarde, pero todo va muy bien.
fuente
Esto puede suceder cuando se vincula a msvcrt.dll en lugar de msvcr10.dll (o similar), lo cual es un buen plan. Porque lo liberará para redistribuir la biblioteca en tiempo de ejecución de Visual Studio dentro de su paquete de software final.
Esa solución me ayuda (en Visual Studio 2008):
Este fragmento no es necesario para Visual Studio 6 y su compilador. Por lo tanto, el #ifdef.
fuente
Para traer más confusión en este hilo ya rico, me topé con el mismo externo no resuelto en fprintf
Incluso si en mi caso fue en un contexto bastante diferente: bajo Visual Studio 2005 (Visual Studio 8.0) y el error estaba ocurriendo en mi propio código (el mismo que estaba compilando), no en un tercero.
Sucedió que este error fue provocado por la opción / MD en mis banderas del compilador. Cambiar a / MT eliminó el problema. Esto es extraño porque, por lo general, la vinculación estática (MT) plantea más problemas que dinámicamente (MD) ... pero en caso de que sirva a otros, lo puse allí.
fuente
En mi caso, este error proviene de mi prueba para eliminar las dependencias de la biblioteca de tiempo de ejecución dependiente de la versión de MSVC (msvcr10.dll más o menos) y / o eliminar también la biblioteca de tiempo de ejecución estática, para eliminar el exceso de grasa de mis ejecutables.
Así que uso el modificador de enlace / NODEFAULTLIB, mi "msvcrt-light.lib" hecho por mí mismo (busque en Google cuando lo necesite), y
mainCRTStartup()
/WinMainCRTStartup()
entradas .Es en mi humilde opinión desde Visual Studio 2015, así que me limité a los compiladores más antiguos.
Sin embargo, definir el símbolo _NO_CRT_STDIO_INLINE elimina todas las molestias, y una aplicación simple "Hello World" es nuevamente 3 KB pequeña y no depende de DLL inusuales. Probado en Visual Studio 2017.
fuente
Pegue este código en cualquiera de sus archivos fuente y vuelva a compilar. Trabajó para mi !
#include stdio.h
ARCHIVO _iob [3];
ARCHIVO * __cdecl __iob_func (void) {
_iob [0] = * stdin;
_iob [0] = * stdout;
_iob [0] = * stderr;
return _iob;
}
fuente