Come risolvere l'errore LNK2019: simbolo esterno non risolto - funzione?


99

Ottengo questo errore, ma non so come risolverlo.

Sto usando Visual Studio 2013. Ho creato il nome della soluzione MyProjectTest Questa è la struttura della mia soluzione di test:

La struttura

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

Sono un principiante; questo è un programma semplice e funziona senza errori. Ho letto su Internet e mi sono interessato allo unit test, quindi ho creato un progetto di test:

File> Nuovo> Progetto ...> Installato> Modelli> Visual C ++> Test> Progetto unit test nativo>

Nome: UnitTest1 Soluzione: Aggiungi alla soluzione Quindi la posizione passa automaticamente al percorso della soluzione aperta corrente Questa è la struttura delle cartelle della soluzione:

Struttura delle cartelle

Ho modificato solo il file 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
        }

    };
}

Ma ottengo l'errore LNK2019: simbolo esterno non risolto. So che manca l'implementazione della funzione multipla . Ho provato a eliminare il file function.cpp e ho sostituito la dichiarazione con la definizione, ed è stato eseguito. Tuttavia, non è consigliabile scrivere sia la dichiarazione che la definizione nello stesso file. Come posso correggere questo errore senza farlo? Devo sostituire con #include "../MyProjectTest/function.cpp"nel file unittest.cpp? (Non sono molto bravo in inglese. Grazie)



6
ATTENZIONE In un ambiente Windows , le librerie statiche hanno .LIBun'estensione di file. Per complicare le cose ... le librerie di collegamento dinamico (cioè *.DLL) possono avere una libreria di importazione accompagnata che ha anche .LIBun'estensione di file. Questa libreria di importazione elenca tutte le chicche fornite da *.DLL. Per maggiori informazioni leggere: Guida per principianti ai linker
Pressacco

4
Perché dovrebbe stare attento ??
Marshal Craft

Risposte:


80

Un'opzione potrebbe essere quella di includere function.cppnel UnitTest1progetto, ma potrebbe non essere la struttura della soluzione più ideale. La risposta breve al tuo problema è che durante la creazione del UnitTest1progetto, il compilatore e il linker non hanno idea che function.cppesista e non hanno nulla da collegare che contenga una definizione multiple. Un modo per risolvere questo problema è utilizzare il collegamento di librerie.

Poiché i tuoi unit test sono in un progetto diverso, presumo che la tua intenzione sia quella di rendere quel progetto un programma di unit test autonomo. Con le funzioni che stai testando situate in un altro progetto, è possibile costruire quel progetto in una libreria collegata dinamicamente o staticamente. Le librerie statiche sono collegate ad altri programmi in fase di compilazione e hanno l'estensione .lib, mentre le librerie dinamiche sono collegate in fase di runtime e hanno l'estensione .dll. Per la mia risposta preferirò le librerie statiche.

Puoi trasformare il tuo primo programma in una libreria statica modificandolo nelle proprietà del progetto. Dovrebbe esserci un'opzione nella scheda Generale in cui il progetto è impostato per creare un eseguibile ( .exe). Puoi cambiarlo in .lib. Il .libfile verrà creato nella stessa posizione del file .exe.

Nel tuo UnitTest1progetto, puoi andare alle sue proprietà e nella scheda Linker nella categoria Directory di libreria aggiuntive, aggiungere il percorso a cui MyProjectTestcostruire. Quindi, per Dipendenze aggiuntive nella scheda Linker - Input, aggiungi il nome della tua libreria statica, molto probabilmente MyProjectTest.lib.

Ciò dovrebbe consentire la realizzazione del tuo progetto. Si noti che in questo modo, MyProjectTestnon sarà un programma eseguibile autonomo a meno che non si modifichino le proprietà di compilazione secondo necessità, il che sarebbe tutt'altro che ideale.


In "Linker-> Input Tab", ho dovuto aggiungere il prefisso "(OutDir)" per la libreria statica, ovvero "$ (OutDir) MyProjectTest.lib", sebbene la posizione di "MyProject" e "MyTestProject" rimanga nella stessa cartella principale .
Pabitra Dash

13
Quindi ogni volta che vuoi eseguire unit test dovresti convertire il tuo progetto testee in una libreria statica, e ogni volta in cui vuoi eseguire effettivamente il tuo programma lo converti di nuovo in un eseguibile, come è questa una soluzione?
A. Smoliak

1
Se MyProjectTest è una dll, possiamo testarlo? Dobbiamo solo aggiungere l'importazione lib o dobbiamo aggiungere i file obj?
partire dal

"Puoi trasformare il tuo primo programma in una libreria statica modificandolo nelle proprietà del progetto. Ci dovrebbe essere un'opzione nella scheda Generale in cui il progetto è impostato per creare un eseguibile (.exe). Puoi cambiarlo in .lib Il file .lib verrà creato nella stessa posizione del file .exe "Fare questo è stato sufficiente per il mio caso. Il resto è stato già gestito da VS.
Ekrem Solmaz

39

Nella struttura ad albero delle soluzioni di Visual Studio fare clic con il pulsante destro del mouse sul progetto "UnitTest1" quindi su Aggiungi -> Elemento esistente -> scegliere il file ../MyProjectTest/function.cpp


4
Nota che i file effettivi non vengono copiati o spostati in ProjDir.
Laurie Stearn

Questo metodo ha risolto problemi simili durante il tentativo di aggiungere c ++ lib a un progetto CLI.
Deshan

17

Poiché voglio che il mio progetto venga compilato in un EXE autonomo, ho collegato il progetto UnitTest al file function.obj generato da function.cpp e funziona. Fare clic con il pulsante destro del mouse sul progetto "UnitTest1"> Proprietà di configurazione> Linker> Input> Dipendenze aggiuntive> aggiungere ".. \ MyProjectTest \ Debug \ function.obj"


1
Che ne dici del caso in cui MyProjectTest è una dll? Puoi impostarlo?
partire dal

Se abbiamo molti file obj. possiamo aggiungere qualcosa come questo * .obj? La tua soluzione ha funzionato con me ma non voglio aggiungere manualmente ogni nuovo file obj.
partire dal

10

Mi sono imbattuto in questo problema in Visual Studio 2013. A quanto pare ora, avere due progetti nella stessa soluzione e impostare le dipendenze non è sufficiente. È necessario aggiungere un riferimento al progetto tra di loro. Fare quello:

  1. Fare clic con il pulsante destro del mouse sul progetto nella soluzione Esplora
  2. Fare clic su Aggiungi => Riferimenti ...
  3. Fare clic sul pulsante Aggiungi nuovo riferimento
  4. Seleziona le caselle per i progetti su cui si basa questo progetto
  5. Fare clic su OK

Cosa intendi impostando le dipendenze? Ho aggiunto il riferimento ma si è comunque lamentato. devblogs.microsoft.com/cppblog/cpp-testing-in-visual-studio ha suggerito che sarebbe stato sufficiente.
tschumann

8

si è scoperto che stavo usando file .c con file .cpp. rinominare .c in .cpp ha risolto il mio problema.


6

Un altro modo per ottenere questo errore del linker (come lo ero io) è se stai esportando un'istanza di una classe da una dll ma non hai dichiarato quella classe stessa come 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

Quindi, anche se principalmente stavo esportando solo un'istanza della classe Book chiamata booksopra, ho dovuto dichiarare la Bookclasse come classe di esportazione / importazione, altrimenti la chiamata book.WordCount()nell'altra dll causava un errore di collegamento.


2

Questo è successo a me, quindi ho pensato di condividere la mia soluzione, per quanto semplice fosse:

Controllare il set di caratteri di entrambi i progetti in Proprietà di configurazione -> Generale -> Set di caratteri

Il mio progetto UnitTest utilizzava il set di caratteri predefinito Multi-Byte mentre le mie librerie erano in Unicode .
La mia funzione utilizzava un TCHAR come parametro. Di conseguenza nella mia libreria il mio TCHAR è stato trasformato in un WCHAR ma era un carattere * sul mio UnitTest: il simbolo era diverso perché i parametri non erano davvero gli stessi alla fine.


1

Ho appena scoperto che si LNK2019verifica durante la compilazione in Visual Studio 2015 se si dimentica di fornire una definizione per una funzione dichiarata all'interno di una classe.

L'errore del linker era altamente criptico, ma ho ristretto ciò che mancava leggendo l'errore e fornito la definizione al di fuori della classe per chiarirlo.


Il problema in alcuni casi è che le intestazioni contenenti le definizioni di classe sono tutte ben referenziate / incluse, ma i loro cpp corrispondenti potrebbero non essere resi disponibili al linker. Il modo migliore per verificare è sfogliare le dipendenze esterne del progetto in Esplora soluzioni. Tuttavia, sarebbe utile per VS emettere un qualche tipo di avviso di esistenza / inclusione di file in merito all'errore.
Laurie Stearn

1

nel mio caso, imposta il file cpp su "C / C ++ compiler" in proprietà -> generale risolvi l'errore LNK2019.


0

Per me funziona, se aggiungo questa linea soffietto in .vcxprojnel itemGroupfile di cpp, che è collegato al file di intestazione.

<ClCompile Include="file.cpp" />

0

In Visual Studio 2017, se si desidera testare i membri pubblici, è sufficiente inserire il progetto reale e il progetto di test nella stessa soluzione e aggiungere un riferimento al progetto reale nel progetto di test.

Per ulteriori dettagli, vedere Unit Testing C ++ in Visual Studio dal blog MSDN. Puoi anche selezionare Scrivi unit test per C / C ++ in Visual Studio e Usa Microsoft Unit Testing Framework per C ++ in Visual Studio , quest'ultimo se devi testare membri non pubblici e devi inserire i test nello stesso progetto come il tuo vero codice.

Nota che le cose che vuoi testare dovranno essere esportate usando __declspec(dllexport). Per ulteriori dettagli, vedere Esportazione da una DLL utilizzando __declspec (dllexport) .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.