Wie löse ich den Fehler LNK2019: ungelöste externe Symbolfunktion?

99

Ich erhalte diesen Fehler, weiß aber nicht, wie ich ihn beheben soll.

Ich verwende Visual Studio 2013. Ich habe den Lösungsnamen MyProjectTest erstellt. Dies ist die Struktur meiner Testlösung:

Die Struktur

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

Ich bin ein Anfänger; Dies ist ein einfaches Programm, das fehlerfrei ausgeführt wird. Ich habe im Internet gelesen und mich für den Unit-Test interessiert, also habe ich ein Testprojekt erstellt:

Datei> Neu> Projekt ...> Installiert> Vorlagen> Visual C ++> Test> Native Unit Test Project>

Name: UnitTest1 Lösung: Zur Lösung hinzufügen Dann wird der Speicherort automatisch auf den Pfad der aktuell geöffneten Lösung umgeschaltet. Dies ist die Ordnerstruktur der Lösung:

Ordnerstruktur

Ich habe nur die Datei unittest1.cpp bearbeitet:

#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
        }

    };
}

Aber ich bekomme den Fehler LNK2019: ungelöstes externes Symbol. Ich weiß, dass die Implementierung der Funktion multiple fehlt. Ich habe versucht, die Datei function.cpp zu löschen, die Deklaration durch die Definition ersetzt und sie ausgeführt. Es wird jedoch nicht empfohlen, sowohl die Deklaration als auch die Definition in dieselbe Datei zu schreiben. Wie kann ich diesen Fehler beheben, ohne das zu tun? Sollte ich durch #include "../MyProjectTest/function.cpp"in der Datei unittest.cpp ersetzen ? (Ich kann nicht sehr gut Englisch. Danke)

phibao37
quelle
6
VORSICHT In einer Windows- Umgebung haben statische Bibliotheken eine .LIBDateierweiterung. Um die Sache zu verkomplizieren ... können dynamische Linkbibliotheken (dh *.DLL) eine zugehörige Importbibliothek haben, die auch eine .LIBDateierweiterung hat. Diese Importbibliothek listet alle von der *.DLL. Weitere Informationen finden Sie unter: Anfängerleitfaden für Linker
Pressacco
4
Warum sollte er vorsichtig sein?
Marschall Handwerk

Antworten:

80

Eine Möglichkeit wäre, function.cppin Ihr UnitTest1Projekt aufzunehmen, aber dies ist möglicherweise nicht die idealste Lösungsstruktur. Die kurze Antwort auf Ihr Problem lautet, dass UnitTest1der Compiler und der Linker beim Erstellen Ihres Projekts keine Ahnung haben, was function.cppvorhanden ist, und auch nichts zu verknüpfen haben, das eine Definition von enthält multiple. Eine Möglichkeit, dies zu beheben, besteht darin, Bibliotheken zu verknüpfen.

Da sich Ihre Unit-Tests in einem anderen Projekt befinden, gehe ich davon aus, dass Sie beabsichtigen, dieses Projekt zu einem eigenständigen Unit-Test-Programm zu machen. Mit den Funktionen, die Sie testen, in einem anderen Projekt können Sie dieses Projekt entweder in einer dynamisch oder statisch verknüpften Bibliothek erstellen. Statische Bibliotheken sind zur Erstellungszeit mit anderen Programmen verknüpft und haben die Erweiterung .lib, und dynamische Bibliotheken sind zur Laufzeit verknüpft und haben die Erweiterung .dll. Für meine Antwort bevorzuge ich statische Bibliotheken.

Sie können Ihr erstes Programm in eine statische Bibliothek verwandeln, indem Sie es in den Projekteigenschaften ändern. Auf der Registerkarte Allgemein sollte eine Option vorhanden sein, mit der das Projekt auf eine ausführbare Datei ( .exe) erstellt werden soll. Sie können dies in ändern .lib. Die .libDatei wird an derselben Stelle wie die erstellt .exe.

In Ihrem UnitTest1Projekt können Sie zu seinen Eigenschaften wechseln und auf der Registerkarte Linker in der Kategorie Zusätzliche Bibliotheksverzeichnisse den Pfad hinzufügen, zu dem MyProjectTestBuilds erstellt werden. Fügen Sie dann für zusätzliche Abhängigkeiten auf der Registerkarte Linker - Eingabe höchstwahrscheinlich den Namen Ihrer statischen Bibliothek hinzu MyProjectTest.lib.

Damit sollte Ihr Projekt erstellt werden können. Beachten Sie, dass dies MyProjectTestkein eigenständiges ausführbares Programm ist, es sei denn, Sie ändern die Build-Eigenschaften nach Bedarf, was nicht ideal wäre.

Kevintodisco
quelle
In 'Linker-> Input Tab' musste ich '(OutDir)' für die statische Bibliothek '$ (OutDir) MyProjectTest.lib' voranstellen, obwohl sich der Speicherort von 'MyProject' und 'MyTestProject' im selben Stammordner befand .
Pabitra Dash
13
Jedes Mal, wenn Sie Unit-Tests ausführen möchten, sollten Sie Ihr Testee-Projekt in eine statische Bibliothek konvertieren. Jedes Mal, wenn Sie Ihr Programm tatsächlich ausführen möchten, konvertieren Sie es zurück in eine ausführbare Datei. Wie ist dies eine Lösung?
A. Smoliak
1
Wenn MyProjectTest eine DLL ist, können wir sie testen? Wir fügen nur die Importbibliothek hinzu oder müssen wir die obj-Dateien hinzufügen?
Aviit
"Sie können Ihr erstes Programm in eine statische Bibliothek verwandeln, indem Sie es in den Projekteigenschaften ändern. Auf der Registerkarte" Allgemein "sollte eine Option vorhanden sein, mit der das Projekt auf eine ausführbare Datei (.exe) erstellt werden kann. Sie können dies in .lib ändern Die .lib-Datei wird an derselben Stelle wie die .exe-Datei erstellt. "Dies war für meinen Fall ausreichend. Der Rest wurde bereits von VS erledigt.
Ekrem Solmaz
38

Klicken Sie im Visual Studio-Lösungsbaum mit der rechten Maustaste auf das Projekt 'UnitTest1' und dann auf Hinzufügen -> Vorhandenes Element -> wählen Sie die Datei ../MyProjectTest/function.cpp

Niyaz Ivanov
quelle
4
Beachten Sie, dass die tatsächlichen Dateien nicht kopiert oder in das ProjDir verschoben werden.
Laurie Stearn
Diese Methode löste ähnliche Probleme beim Versuch, einem CLI-Projekt c ++ lib hinzuzufügen.
Deshan
17

Da ich möchte, dass mein Projekt zu einer eigenständigen EXE-Datei kompiliert wird, habe ich das UnitTest-Projekt mit der aus der function.cpp generierten Datei function.obj verknüpft und es funktioniert. Klicken Sie mit der rechten Maustaste auf das Projekt 'UnitTest1'> Konfigurationseigenschaften> Linker> Eingabe> Zusätzliche Abhängigkeiten> fügen Sie ".. \ MyProjectTest \ Debug \ function.obj" hinzu.

Harrygg
quelle
1
Wie wäre es mit dem Fall, wenn MyProjectTest eine DLL ist? Können Sie sich darauf einstellen?
Aviit
Wenn wir viele obj-Dateien haben. können wir so etwas hinzufügen * .obj? Ihre Lösung hat bei mir funktioniert, aber ich möchte nicht alle neuen obj-Dateien manuell hinzufügen.
Aviit
10

Ich bin gerade in Visual Studio 2013 auf dieses Problem gestoßen. Anscheinend reicht es jetzt nicht mehr aus, zwei Projekte in derselben Lösung zu haben und die Abhängigkeiten festzulegen. Sie müssen eine Projektreferenz zwischen ihnen hinzufügen. Das zu tun:

  1. Klicken Sie in der Lösungssuche mit der rechten Maustaste auf das Projekt
  2. Klicken Sie auf Hinzufügen => Referenzen ...
  3. Klicken Sie auf die Schaltfläche Neue Referenz hinzufügen
  4. Aktivieren Sie die Kontrollkästchen für die Projekte, auf die sich dieses Projekt stützt
  5. OK klicken
Kevin Dill
quelle
Was meinen Sie mit dem Festlegen der Abhängigkeiten? Ich habe die Referenz hinzugefügt, aber sie hat sich immer noch beschwert. devblogs.microsoft.com/cppblog/cpp-testing-in-visual-studio schlug vor, dass dies ausreichen würde.
Tschumann
8

Es stellte sich heraus, dass ich .c-Dateien mit .cpp-Dateien verwendete. Das Umbenennen von .c in .cpp hat mein Problem gelöst.

cahit beyaz
quelle
6

Eine andere Möglichkeit, diesen Linkerfehler zu erhalten (wie ich es war), besteht darin, dass Sie eine Instanz einer Klasse aus einer DLL exportieren , diese Klasse selbst jedoch nicht als Import / Export deklariert haben.

 #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

Obwohl ich hauptsächlich nur eine Instanz der bookoben genannten Book-Klasse exportierte , musste ich die BookKlasse auch als Export- / Importklasse deklarieren, da sonst das Aufrufen book.WordCount()der anderen DLL einen Linkfehler verursachte.

zar
quelle
2

Dies passierte mir und ich dachte, ich könnte meine Lösung teilen, so einfach es war:

Überprüfen Sie den Zeichensatz beider Projekte unter Konfigurationseigenschaften -> Allgemein -> Zeichensatz

Mein UnitTest-Projekt verwendete das Standard-Zeichensatz- Multi-Byte, während sich meine Bibliotheken in Unicode befanden .
Meine Funktion war die Verwendung eines TCHAR als Parameter. Als Ergebnis in meinem lib meines TCHAR wurde umgewandelt in eine WCHAR aber es war ein char * auf meinem Unittest: Das Symbol war anders , weil die Parameter am Ende wirklich nicht das gleiche waren.

Enyx
quelle
1

Ich habe gerade festgestellt, dass dies LNK2019beim Kompilieren in Visual Studio 2015 auftritt, wenn vergessen wird, eine Definition für eine deklarierte Funktion innerhalb einer Klasse anzugeben.

Der Linker-Fehler war sehr kryptisch, aber ich habe das Fehlen eingegrenzt, indem ich den Fehler durchgelesen und die Definition außerhalb der Klasse angegeben habe, um dies zu klären.

Matschig
quelle
In einigen Fällen besteht das Problem darin, dass die Header, die die Klassen-Defs enthalten, alle gut referenziert / enthalten sind, die entsprechenden cpps dem Linker jedoch möglicherweise nicht zur Verfügung gestellt werden . Am besten überprüfen Sie dies, indem Sie im Projektmappen-Explorer durch die externen Abhängigkeiten des Projekts blättern. Für VS wäre es jedoch von Vorteil, eine Art Warnung zum Vorhandensein / Einschließen von Dateien in Bezug auf den Fehler auszugeben.
Laurie Stearn
1

In meinem Fall setzen Sie die CPP-Datei in der Eigenschaft -> Allgemein, um den LNK2019-Fehler zu beheben, auf "C / C ++ - Compiler".

pivnothebearrrrrrrrr
quelle
0

Für mich funktioniert, wenn ich diese Zeile unten .vcxprojin die itemGroupCPP-Datei einfüge, die mit der Header-Datei verbunden ist.

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

Wenn Sie in Visual Studio 2017 öffentliche Mitglieder testen möchten, fügen Sie einfach Ihr reales Projekt und Ihr Testprojekt in dieselbe Lösung ein und fügen Sie im Testprojekt einen Verweis auf Ihr reales Projekt hinzu.

Weitere Informationen finden Sie unter C ++ - Komponententests in Visual Studio im MSDN-Blog. Sie können auch Unit-Tests für C / C ++ in Visual Studio schreiben sowie Microsoft Unit Testing Framework für C ++ in Visual Studio verwenden aktivieren . Letzteres gilt, wenn Sie nicht öffentliche Mitglieder testen und die Tests in dasselbe Projekt einfügen müssen als dein echter Code.

Beachten Sie, dass Dinge, die Sie testen möchten, mit exportiert werden müssen __declspec(dllexport). Weitere Informationen finden Sie unter Exportieren aus einer DLL mit __declspec (dllexport) .

user276648
quelle