¿Cómo solucionar el error LNK2019: símbolo externo no resuelto - función?

99

Recibo este error, pero no sé cómo solucionarlo.

Estoy usando Visual Studio 2013. Hice el nombre de la solución MyProjectTest Esta es la estructura de mi solución de prueba:

La estructura

- función.h

#ifndef MY_FUNCTION_H
#define MY_FUNCTION_H

int multiple(int x, int y);
#endif

-function.cpp

#include "function.h"

int multiple(int x, int y){
    return x*y;
}

- main.cpp

#include <iostream>
#include <cstdlib>
#include "function.h"
using namespace std;

int main(){
    int a, b;
    cin >> a >> b;
    cout << multiple(a, b) << endl;

    system("pause");
    return 0;
}

Soy un principiante; este es un programa simple y se ejecuta sin errores. Leí en Internet y me interesé en la prueba unitaria, así que creé un proyecto de prueba:

Archivo> Nuevo> Proyecto ...> Instalado> Plantillas> Visual C ++> Prueba> Proyecto de prueba de unidad nativa>

Nombre: UnitTest1 Solución: Agregar a la solución Luego, la ubicación cambió automáticamente a la ruta de la solución abierta actual Esta es la estructura de carpetas de la solución:

Estructura de carpetas

Solo edité el archivo unittest1.cpp:

#include "stdafx.h"
#include "CppUnitTest.h"
#include "../MyProjectTest/function.h"

using namespace Microsoft::VisualStudio::CppUnitTestFramework;

namespace UnitTest1
{       
    TEST_CLASS(UnitTest1)
    {
    public:

        TEST_METHOD(TestEqual)
        {

            Assert::AreEqual(multiple(2, 3), 6);
            // TODO: Your test code here
        }

    };
}

Pero obtengo el error LNK2019: símbolo externo sin resolver. Sé que falta la implementación de la función múltiple . Intenté eliminar el archivo function.cpp y reemplacé la declaración con la definición, y se ejecutó. Pero no se recomienda escribir tanto la declaración como la definición en el mismo archivo. ¿Cómo puedo solucionar este error sin hacer eso? ¿Debo reemplazar con #include "../MyProjectTest/function.cpp"en el archivo unittest.cpp? (No soy muy bueno en inglés. Gracias)

phibao37
fuente
6
TENGA CUIDADO En un entorno Windows , las bibliotecas estáticas tienen una .LIBextensión de archivo. Para complicar las cosas ... las bibliotecas de enlaces dinámicos (es decir *.DLL) pueden tener una biblioteca de importación adjunta que también tiene una .LIBextensión de archivo. Esta biblioteca de importación enumera todos los beneficios proporcionados por *.DLL. Para obtener más información, lea: Guía para principiantes de
vinculadores
4
¿Por qué debería tener cuidado?
Marshal Craft

Respuestas:

80

Una opción sería incluirla function.cppen su UnitTest1proyecto, pero puede que esa no sea la estructura de solución más ideal. La respuesta corta a su problema es que al construir su UnitTest1proyecto, el compilador y el enlazador no tienen idea de que function.cppexiste, y tampoco tienen nada para vincular que contenga una definición de multiple. Una forma de solucionar este problema es utilizar bibliotecas de enlace.

Dado que sus pruebas unitarias están en un proyecto diferente, supongo que su intención es hacer de ese proyecto un programa independiente de pruebas unitarias. Con las funciones que está probando ubicadas en otro proyecto, es posible construir ese proyecto en una biblioteca vinculada dinámica o estáticamente. Las bibliotecas estáticas están vinculadas a otros programas en el momento de la compilación y tienen la extensión .lib, y las bibliotecas dinámicas están vinculadas en tiempo de ejecución y tienen la extensión .dll. Para mi respuesta, preferiré bibliotecas estáticas.

Puede convertir su primer programa en una biblioteca estática cambiándolo en las propiedades del proyecto. Debería haber una opción en la pestaña General donde el proyecto está configurado para compilarse en un ejecutable ( .exe). Puede cambiar esto a .lib. El .libarchivo se creará en el mismo lugar que el .exe.

En su UnitTest1proyecto, puede ir a sus propiedades y, en la pestaña Vinculador, en la categoría Directorios de biblioteca adicionales, agregue la ruta a la que se MyProjectTestcompila. Luego, para Dependencias adicionales en el Vinculador - pestaña Entrada, agregue el nombre de su biblioteca estática, muy probablemente MyProjectTest.lib.

Eso debería permitir que su proyecto se desarrolle. Tenga en cuenta que al hacer esto, MyProjectTestno será un programa ejecutable independiente a menos que cambie sus propiedades de compilación según sea necesario, lo que sería menos que ideal.

kevintodisco
fuente
En 'Linker-> Input Tab', tuve que prefijar '(OutDir)' para la biblioteca estática, que es '$ (OutDir) MyProjectTest.lib', aunque la ubicación de 'MyProject' y 'MyTestProject' se mantuvo en la misma carpeta raíz .
Pabitra Dash
13
Entonces, cada vez que desee ejecutar pruebas unitarias, debe convertir su proyecto testee en una biblioteca estática, y cada vez que realmente desee ejecutar su programa, vuelva a convertirlo en un ejecutable, ¿cómo es esto una solución?
A. Smoliak
1
Si MyProjectTest es un dll, ¿podemos probarlo? ¿Simplemente agregamos la lib de importación o debemos agregar los archivos obj?
aviit
"Puede convertir su primer programa en una biblioteca estática cambiándolo en las propiedades del proyecto. Debería haber una opción en la pestaña General donde el proyecto está configurado para compilarse en un ejecutable (.exe). Puede cambiar esto a .lib . El archivo .lib se construirá en el mismo lugar que el .exe "Hacer esto fue suficiente para mi caso. El resto ya lo manejó VS.
Ekrem Solmaz
39

En el árbol de soluciones de Visual Studio, haga clic con el botón derecho en el proyecto 'UnitTest1' y luego en Agregar -> Elemento existente -> elija el archivo ../MyProjectTest/function.cpp

Niyaz Ivanov
fuente
4
Tenga en cuenta que los archivos reales no se copian ni se mueven al ProjDir.
Laurie Stearn
Este método resolvió problemas similares que ocurrieron al intentar agregar c ++ lib a un proyecto CLI.
Deshan
17

Como quiero que mi proyecto se compile en un EXE independiente, vinculé el proyecto UnitTest al archivo function.obj generado a partir de function.cpp y funciona. Haga clic con el botón derecho en el proyecto 'UnitTest1'> Propiedades de configuración> Vinculador> Entrada> Dependencias adicionales> agregar ".. \ MyProjectTest \ Debug \ function.obj"

Harrygg
fuente
1
¿Qué tal el caso cuando MyProjectTest es una dll? ¿Puedes prepararlo?
AVIIT
Si tenemos muchos archivos obj. ¿Podemos agregar algo como esto * .obj? Su solución funcionó conmigo, pero no quiero agregar manualmente todos los archivos obj nuevos.
aviit
10

Me encontré con este problema en Visual Studio 2013. Aparentemente ahora, tener dos proyectos en la misma solución y configurar las dependencias no es suficiente. Debe agregar una referencia de proyecto entre ellos. Para hacer eso:

  1. Haga clic derecho en el proyecto en la solución explorar
  2. Haga clic en Agregar => Referencias ...
  3. Haga clic en el botón Agregar nueva referencia
  4. Marque las casillas de los proyectos en los que se basa este proyecto
  5. Haga clic en Aceptar
Kevin Dill
fuente
¿Qué quiere decir con establecer las dependencias? Agregué la referencia pero todavía se quejaba. devblogs.microsoft.com/cppblog/cpp-testing-in-visual-studio sugirió que sería suficiente.
tschumann
8

resultó que estaba usando archivos .c con archivos .cpp. cambiar el nombre de .c a .cpp resolvió mi problema.

cahit beyaz
fuente
6

Otra forma en que puede obtener este error del vinculador (como yo) es si está exportando una instancia de una clase desde un dll pero no ha declarado esa clase en sí como importación / exportación.

 #ifdef  MYDLL_EXPORTS 
    #define DLLEXPORT __declspec(dllexport)  
 #else
    #define DLLEXPORT __declspec(dllimport)  
 #endif

class DLLEXPORT Book // <--- this class must also be declared as export/import
{
public: 
    Book();
    ~Book();
    int WordCount();
};

DLLEXPORT extern Book book; // <-- This is what I really wanted, to export book object

Entonces, aunque principalmente estaba exportando solo una instancia de la clase Book llamada bookanteriormente, tuve que declarar la Bookclase como clase de exportación / importación y, de lo contrario, llamar book.WordCount()a la otra dll estaba causando un error de enlace.

zar
fuente
2

Esto me sucedió, así que pensé en compartir mi solución, tan simple como era:

Compruebe el conjunto de caracteres de ambos proyectos en Propiedades de configuración -> General -> Conjunto de caracteres

Mi proyecto UnitTest estaba usando el conjunto de caracteres predeterminado Multi-Byte mientras que mis bibliotecas estaban en Unicode .
Mi función estaba usando un TCHAR como parámetro. Como resultado, en mi lib mi TCHAR se transformó en un WCHAR pero era un char * en mi UnitTest: el símbolo era diferente porque los parámetros en realidad no eran los mismos al final.

Enyx
fuente
1

Acabo de descubrir que LNK2019ocurre durante la compilación en Visual Studio 2015 si me olvido de proporcionar una definición para una función declarada dentro de una clase.

El error del vinculador fue muy críptico, pero reduje lo que faltaba leyendo el error y proporcioné la definición fuera de la clase para aclararlo.

Pulposo
fuente
El problema en algunos casos es que los encabezados que contienen las definiciones de clase están todos bien referenciados / incluidos, pero es posible que sus correspondientes cpps no estén disponibles para el enlazador. La mejor forma de comprobarlo es hojear las dependencias externas del proyecto en el Explorador de soluciones. Sin embargo, sería beneficioso para VS emitir algún tipo de advertencia de existencia / inclusión de archivos con respecto al error.
Laurie Stearn
1

en mi caso, establezca el archivo cpp en "C / C ++ compiler" en la propiedad -> general resolver el error LNK2019.

pivnothebearrrrrrrrr
fuente
0

Para mí funciona, si añado esta línea de abajo en .vcxprojen itemGrouparchivo CPP, que está conectado al archivo de cabecera.

<ClCompile Include="file.cpp" />
Nejc Galof
fuente
0

En Visual Studio 2017, si desea probar miembros públicos, simplemente coloque su proyecto real y el proyecto de prueba en la misma solución, y agregue una referencia a su proyecto real en el proyecto de prueba.

Consulte Pruebas unitarias de C ++ en Visual Studio en el blog de MSDN para obtener más detalles. También puede verificar Escribir pruebas unitarias para C / C ++ en Visual Studio , así como Usar el Marco de pruebas unitarias de Microsoft para C ++ en Visual Studio , este último si necesita probar miembros no públicos y necesita poner las pruebas en el mismo proyecto como su código real.

Tenga en cuenta que las cosas que desee probar deberán exportarse mediante __declspec(dllexport). Consulte Exportar desde una DLL con __declspec (dllexport) para obtener más detalles.

usuario276648
fuente