Comment résoudre l'erreur LNK2019: symbole externe non résolu - fonction?

99

J'obtiens cette erreur, mais je ne sais pas comment la corriger.

J'utilise Visual Studio 2013. J'ai créé le nom de la solution MyProjectTest Voici la structure de ma solution de test:

La structure

- fonction.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;
}

Je suis un débutant; c'est un programme simple et il fonctionne sans erreur. J'ai lu sur Internet et je me suis intéressé au test unitaire, j'ai donc créé un projet de test:

Fichier> Nouveau> Projet ...> Installé> Modèles> Visual C ++> Test> Projet de test d'unité native>

Nom: UnitTest1 Solution: Ajouter à la solution Ensuite, l'emplacement est automatiquement basculé vers le chemin de la solution ouverte actuelle Voici la structure de dossiers de la solution:

Structure des dossiers

J'ai seulement édité le fichier 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
        }

    };
}

Mais j'obtiens l'erreur LNK2019: symbole externe non résolu. Je sais que l'implémentation de la fonction multiple est manquante. J'ai essayé de supprimer le fichier function.cpp et j'ai remplacé la déclaration par la définition, et elle a fonctionné. Mais écrire à la fois la déclaration et la définition dans le même fichier n'est pas recommandé. Comment puis-je corriger cette erreur sans faire cela? Dois-je remplacer par #include "../MyProjectTest/function.cpp"dans le fichier unittest.cpp? (Je ne suis pas très bon en anglais. Merci)

phibao37
la source
6
ATTENTION Dans un environnement Windows , les bibliothèques statiques ont une .LIBextension de fichier. Pour compliquer les choses ... les bibliothèques de liens dynamiques (c'est-à-dire *.DLL) peuvent avoir une bibliothèque d'importation associée qui a également une .LIBextension de fichier. Cette bibliothèque d'importation répertorie tous les goodies fournis par le *.DLL. Pour plus d'informations, veuillez lire: Guide du débutant sur les
liens
4
Pourquoi devrait-il faire attention?
maréchal craft

Réponses:

80

Une option serait d'inclure function.cppdans votre UnitTest1projet, mais ce n'est peut-être pas la structure de solution la plus idéale. La réponse courte à votre problème est que lors de la construction de votre UnitTest1projet, le compilateur et l'éditeur de liens n'ont aucune idée de ce qui function.cppexiste et n'ont aucun lien contenant une définition de multiple. Un moyen de résoudre ce problème consiste à utiliser des bibliothèques de liaison.

Étant donné que vos tests unitaires sont dans un projet différent, je suppose que votre intention est de faire de ce projet un programme de test unitaire autonome. Avec les fonctions que vous testez situées dans un autre projet, il est possible de créer ce projet dans une bibliothèque liée dynamiquement ou statiquement. Les bibliothèques statiques sont liées à d'autres programmes au moment de la construction, et ont l'extension .lib, et les bibliothèques dynamiques sont liées au moment de l'exécution et ont l'extension .dll. Pour ma réponse, je préfère les bibliothèques statiques.

Vous pouvez transformer votre premier programme en bibliothèque statique en le modifiant dans les propriétés du projet. Il devrait y avoir une option sous l'onglet Général où le projet est configuré pour générer un exécutable ( .exe). Vous pouvez changer cela en .lib. Le .libfichier sera généré au même endroit que le fichier .exe.

Dans votre UnitTest1projet, vous pouvez accéder à ses propriétés, et sous l'onglet Éditeur de liens dans la catégorie Répertoires de bibliothèques supplémentaires, ajoutez le chemin d'accès aux MyProjectTestbuilds. Ensuite, pour les dépendances supplémentaires sous l'onglet Éditeur de liens - Entrée, ajoutez le nom de votre bibliothèque statique, très probablement MyProjectTest.lib.

Cela devrait permettre à votre projet de se construire. Notez qu'en faisant cela, MyProjectTestne sera pas un programme exécutable autonome à moins que vous ne modifiiez ses propriétés de construction si nécessaire, ce qui serait loin d'être idéal.

kevintodisco
la source
Dans 'Linker-> Input Tab', j'ai dû préfixer '(OutDir)' pour la bibliothèque statique, c'est-à-dire '$ (OutDir) MyProjectTest.lib', bien que l'emplacement de 'MyProject' et 'MyTestProject' soit conservé dans le même dossier racine .
Pabitra Dash
13
Ainsi, chaque fois que vous souhaitez exécuter des tests unitaires, vous devez convertir votre projet testee en une bibliothèque statique, et chaque fois que vous souhaitez réellement exécuter votre programme, vous le reconvertissez en exécutable, comment est-ce une solution?
A. Smoliak
1
Si MyProjectTest est une DLL, pouvons-nous le tester? Nous ajoutons simplement la bibliothèque d'importation ou nous devons ajouter les fichiers obj?
aviit
"Vous pouvez transformer votre premier programme en une bibliothèque statique en le modifiant dans les propriétés du projet. Il devrait y avoir une option sous l'onglet Général où le projet est configuré pour se construire en exécutable (.exe). Vous pouvez le changer en .lib . Le fichier .lib sera construit au même endroit que le .exe "Cela suffisait pour mon cas. Le reste était déjà géré par VS.
Ekrem Solmaz
39

Dans l'arborescence de la solution Visual Studio, cliquez avec le bouton droit sur le projet 'UnitTest1' puis Ajouter -> Élément existant -> choisissez le fichier ../MyProjectTest/function.cpp

Niyaz Ivanov
la source
4
Notez que le ou les fichiers réels ne sont pas copiés ou déplacés vers le ProjDir.
Laurie Stearn
Cette méthode a résolu des problèmes similaires survenus lors de la tentative d'ajout de lib C ++ à un projet CLI.
Deshan
17

Puisque je veux que mon projet soit compilé sur un EXE autonome, j'ai lié le projet UnitTest au fichier function.obj généré à partir de function.cpp et cela fonctionne. Cliquez avec le bouton droit sur le projet 'UnitTest1'> Propriétés de configuration> Linker> Input> Additional Dependencies> add ".. \ MyProjectTest \ Debug \ function.obj"

harrygg
la source
1
Que diriez-vous du cas où MyProjectTest est une DLL? Pouvez-vous vous y préparer?
aviit
Si nous avons de nombreux fichiers obj. pouvons-nous ajouter quelque chose comme ça * .obj? Votre solution a fonctionné avec moi, mais je ne veux pas ajouter manuellement tous les nouveaux fichiers obj.
aviit
10

Je viens de rencontrer ce problème dans Visual Studio 2013. Apparemment maintenant, avoir deux projets dans la même solution et définir les dépendances ne suffit pas. Vous devez ajouter une référence de projet entre eux. Pour faire ça:

  1. Cliquez avec le bouton droit sur le projet dans la solution explorer
  2. Cliquez sur Ajouter => Références ...
  3. Cliquez sur le bouton Ajouter une nouvelle référence
  4. Cochez les cases des projets sur lesquels repose ce projet
  5. Cliquez sur OK
Kevin Dill
la source
Que voulez-vous dire en définissant les dépendances? J'ai ajouté la référence mais il se plaignait toujours. devblogs.microsoft.com/cppblog/cpp-testing-in-visual-studio a suggéré que cela suffirait.
tschumann
8

il s'est avéré que j'utilisais des fichiers .c avec des fichiers .cpp. renommer .c en .cpp a résolu mon problème.

cahit beyaz
la source
6

Une autre façon d'obtenir cette erreur de l'éditeur de liens (comme je l'étais) est si vous exportez une instance d'une classe à partir d'une DLL mais que vous n'avez pas déclaré cette classe elle-même comme import / export.

 #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

Donc, même si principalement j'exportais juste une instance de la classe Book appelée bookci-dessus, j'ai dû déclarer la Bookclasse comme classe d'exportation / importation, sinon l'appel book.WordCount()de l'autre dll provoquait une erreur de lien.

zar
la source
2

Cela m'est arrivé alors j'ai pensé que je pourrais partager ma solution, aussi simple soit-elle:

Vérifiez le jeu de caractères des deux projets dans Propriétés de configuration -> Général -> Jeu de caractères

Mon projet UnitTest utilisait le jeu de caractères par défaut multi-octets alors que mes bibliothèques étaient en Unicode .
Ma fonction utilisait un TCHAR comme paramètre. En conséquence, dans ma lib, mon TCHAR était transformé en un WCHAR mais c'était un char * sur mon UnitTest: le symbole était différent car les paramètres n'étaient vraiment pas les mêmes à la fin.

Enyx
la source
1

Je viens de découvrir que LNK2019 se produit lors de la compilation dans Visual Studio 2015 si vous oubliez de fournir une définition pour une fonction déclarée dans une classe.

L'erreur de l'éditeur de liens était très cryptique, mais j'ai réduit ce qui manquait en lisant l'erreur et j'ai fourni la définition en dehors de la classe pour clarifier cela.

Détrempé
la source
Le problème dans certains cas est que les en-têtes contenant les définitions de classe sont tous bien référencés / inclus mais leurs cpps correspondants peuvent ne pas être mis à la disposition de l'éditeur de liens. La meilleure façon de vérifier est de parcourir les dépendances externes du projet dans l'Explorateur de solutions. Il serait cependant avantageux que VS émette une sorte d'avertissement d'existence / d'inclusion de fichier concernant l'erreur.
Laurie Stearn
1

dans mon cas, définissez le fichier cpp sur "compilateur C / C ++" dans la propriété -> résolution générale de l'erreur LNK2019.

pivnothebearrrrrrrrr
la source
0

Pour moi fonctionne, si j'ajoute ce soufflet ligne .vcxprojdans le itemGroupfichier cpp, qui est relié au fichier d' en- tête.

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

Dans Visual Studio 2017, si vous souhaitez tester des membres publics, placez simplement votre projet réel et votre projet de test dans la même solution et ajoutez une référence à votre projet réel dans le projet de test.

Consultez Test unitaire C ++ dans Visual Studio à partir du blog MSDN pour plus de détails. Vous pouvez également vérifier Écrire des tests unitaires pour C / C ++ dans Visual Studio ainsi que Utiliser le Microsoft Unit Testing Framework pour C ++ dans Visual Studio , ce dernier étant si vous avez besoin de tester des membres non publics et devez placer les tests dans le même projet comme votre vrai code.

Notez que les éléments que vous souhaitez tester devront être exportés à l'aide de __declspec(dllexport). Voir Exportation à partir d'une DLL à l'aide de __declspec (dllexport) pour plus de détails.

utilisateur276648
la source