Bagaimana mengatasi kesalahan LNK2019: simbol eksternal yang tidak terselesaikan - fungsi?


100

Saya mendapatkan kesalahan ini, tetapi saya tidak tahu cara memperbaikinya.

Saya menggunakan Visual Studio 2013. Saya membuat nama solusi MyProjectTest Ini adalah struktur solusi pengujian saya:

Struktur

- function.h

#ifndef MY_FUNCTION_H
#define MY_FUNCTION_H

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

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

Saya seorang pemula; ini adalah program sederhana dan berjalan tanpa kesalahan. Saya membaca di internet dan menjadi tertarik dengan pengujian unit, jadi saya membuat proyek pengujian:

File> New> Project ...> Installed> Templates> Visual C ++> Test> Native Unit Test Project>

Nama: UnitTest1 Solusi: Tambahkan ke solusi Kemudian lokasi dialihkan secara otomatis ke jalur solusi terbuka saat ini Ini adalah struktur folder dari solusi:

Struktur folder

Saya hanya mengedit 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
        }

    };
}

Tetapi saya mendapatkan kesalahan LNK2019: simbol eksternal yang belum terselesaikan. Saya tahu bahwa implementasi fungsi kelipatan hilang. Saya mencoba untuk menghapus file function.cpp dan saya mengganti deklarasi dengan definisi, dan itu berjalan. Namun tidak disarankan untuk menulis deklarasi dan definisi dalam file yang sama. Bagaimana cara memperbaiki kesalahan ini tanpa melakukan itu? Haruskah saya mengganti dengan #include "../MyProjectTest/function.cpp"dalam file unittest.cpp? (Saya tidak terlalu pandai berbahasa Inggris. Terima kasih)



6
HATI-HATI Di lingkungan Windows , pustaka statis memiliki .LIBekstensi file. Untuk memperumit hal-hal ... pustaka tautan dinamis (yaitu *.DLL) dapat memiliki pustaka impor yang menyertai yang juga memiliki .LIBekstensi file. Pustaka impor ini mencantumkan semua barang yang disediakan oleh *.DLL. Untuk informasi lebih lanjut, silakan baca: Panduan Pemula untuk Linkers
Pressacco

5
Kenapa dia harus berhati-hati ??
kerajinan marshal

Jawaban:


81

Salah satu opsi adalah memasukkannya ke function.cppdalam UnitTest1proyek Anda , tetapi itu mungkin bukan struktur solusi yang paling ideal. Jawaban singkat untuk masalah Anda adalah ketika membangun UnitTest1proyek Anda , compiler dan linker tidak mengetahui function.cppkeberadaannya, dan juga tidak memiliki tautan apa pun yang berisi definisi multiple. Cara untuk memperbaikinya adalah dengan menggunakan perpustakaan penautan.

Karena pengujian unit Anda berada dalam proyek yang berbeda, saya berasumsi niat Anda adalah menjadikan proyek itu sebagai program pengujian unit yang berdiri sendiri. Dengan fungsi yang Anda uji terletak di proyek lain, dimungkinkan untuk membangun proyek itu ke pustaka yang terhubung secara dinamis atau statis. Library statis ditautkan ke program lain pada waktu pembuatan, dan memiliki ekstensi .lib, dan library dinamis ditautkan saat runtime, dan memiliki ekstensi .dll. Untuk jawaban saya, saya lebih suka perpustakaan statis.

Anda dapat mengubah program pertama Anda menjadi pustaka statis dengan mengubahnya di properti proyek. Harus ada opsi di bawah tab Umum di mana proyek diatur untuk membangun sebuah executable ( .exe). Anda dapat mengubahnya menjadi .lib. The .libFile akan membangun ke tempat yang sama dengan .exe.

Dalam UnitTest1proyek Anda, Anda dapat membuka propertinya, dan di bawah tab Linker dalam kategori Direktori Perpustakaan Tambahan, tambahkan jalur ke mana MyProjectTestbuild. Kemudian, untuk Dependensi Tambahan di bawah Linker - tab Input, tambahkan nama pustaka statis Anda, kemungkinan besar MyProjectTest.lib.

Itu akan memungkinkan proyek Anda untuk dibangun. Perhatikan bahwa dengan melakukan ini, MyProjectTesttidak akan menjadi program yang dapat dijalankan secara mandiri kecuali Anda mengubah properti build-nya sesuai kebutuhan, yang akan kurang dari ideal.


Di 'Linker-> Input Tab', saya harus mengawali '(OutDir)' untuk library statis, yaitu '$ (OutDir) MyProjectTest.lib', meskipun lokasi 'MyProject' dan 'MyTestProject' disimpan di folder root yang sama .
Pabitra Dash

14
Jadi setiap kali Anda ingin menjalankan pengujian unit, Anda harus mengubah proyek testee Anda menjadi pustaka statis, dan setiap kali Anda benar-benar ingin menjalankan program, Anda mengubahnya kembali menjadi dapat dijalankan, bagaimana solusinya?
A. Smoliak

1
Jika MyProjectTest adalah dll, dapatkah kita mengujinya? Kami hanya menambahkan lib import atau kami harus menambahkan file obj?
aviit

"Anda dapat mengubah program pertama Anda menjadi pustaka statis dengan mengubahnya di properti proyek. Seharusnya ada opsi di bawah tab Umum di mana proyek disetel untuk dibangun ke file yang dapat dieksekusi (.exe). Anda dapat mengubahnya menjadi .lib File .lib akan dibangun di tempat yang sama dengan .exe "Melakukan ini sudah cukup untuk kasus saya. Sisanya sudah ditangani oleh VS.
Ekrem Solmaz

39

Pada pohon solusi Visual Studio klik kanan pada proyek 'UnitTest1' lalu Add -> Existing item -> pilih file ../MyProjectTest/function.cpp


4
Perhatikan bahwa file sebenarnya tidak disalin atau dipindahkan ke ProjDir.
Laurie Stearn

Metode ini memecahkan masalah serupa yang terjadi saat mencoba menambahkan c ++ lib ke proyek CLI.
Deshan

17

Karena saya ingin proyek saya dikompilasi ke EXE mandiri, saya menautkan proyek UnitTest ke file function.obj yang dihasilkan dari function.cpp dan berhasil. Klik kanan pada proyek 'UnitTest1'> Properti Konfigurasi> Linker> Input> Dependensi Tambahan> tambahkan ".. \ MyProjectTest \ Debug \ function.obj"


1
Bagaimana kasus ketika MyProjectTest adalah dll? Bisakah Anda mengaturnya?
aviit

Jika kami memiliki banyak file obj. bisakah kita menambahkan beberapa hal seperti ini * .obj? Solusi Anda berfungsi dengan saya tetapi saya tidak ingin menambahkan setiap file obj baru secara manual.
aviit

10

Saya baru saja mengalami masalah ini di Visual Studio 2013. Ternyata sekarang, memiliki dua proyek dalam solusi yang sama dan pengaturan dependensi saja tidak cukup. Anda perlu menambahkan referensi proyek di antara mereka. Untuk melakukannya:

  1. Klik kanan pada proyek di eksplorasi solusi
  2. Klik Tambah => Referensi ...
  3. Klik tombol Add New Reference
  4. Centang kotak untuk proyek yang diandalkan oleh proyek ini
  5. Klik OK

Apa yang Anda maksud dengan mengatur dependensi? Saya menambahkan referensi tetapi masih mengeluh. devblogs.microsoft.com/cppblog/cpp-testing-in-visual-studio menyarankan itu sudah cukup.
tschumann

8

ternyata saya menggunakan file .c dengan file .cpp. mengganti nama .c menjadi .cpp memecahkan masalah saya.


6

Cara lain Anda bisa mendapatkan kesalahan linker ini (seperti yang saya lakukan) adalah jika Anda mengekspor instance kelas dari dll tetapi belum menyatakan kelas itu sendiri sebagai impor / ekspor.

 #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

Jadi meskipun terutama saya mengekspor hanya instance dari kelas Book yang disebut di bookatas, saya harus mendeklarasikan Bookkelas sebagai kelas ekspor / impor juga jika tidak memanggil book.WordCount()dll lainnya menyebabkan kesalahan tautan.


3

Ini terjadi pada saya, jadi saya pikir saya akan membagikan solusi saya, sesederhana itu:

Periksa Kumpulan Karakter dari kedua proyek di Properti Konfigurasi -> Umum -> Kumpulan Karakter

Proyek UnitTest saya menggunakan Set Karakter Multi-Byte default sementara libs saya di Unicode .
Fungsi saya menggunakan TCHAR sebagai parameter. Akibatnya di lib saya saya TCHAR itu berubah menjadi WCHAR tapi itu adalah char * di UnitTest saya: simbol yang berbeda karena parameter benar-benar tidak sama pada akhirnya.


Terima kasih, ini membantu saya memecahkan masalah :)
Perry Qian-MSFT

1

Saya baru saja menemukan itu LNK2019terjadi selama kompilasi di Visual Studio 2015 jika lupa memberikan definisi untuk fungsi yang dideklarasikan di dalam kelas.

Kesalahan penaut sangat samar tetapi saya mempersempit apa yang hilang dengan membaca kesalahan dan memberikan definisi di luar kelas untuk menyelesaikannya.


Masalah dalam beberapa kasus adalah bahwa header yang berisi definisi kelas semuanya direferensikan / disertakan dengan baik tetapi cpps yang sesuai mungkin tidak tersedia untuk linker. Cara terbaik untuk memeriksanya adalah dengan membolak-balik dependensi eksternal proyek di Solution Explorer. Akan bermanfaat bagi VS untuk mengeluarkan semacam peringatan keberadaan / penyertaan file terkait kesalahan tersebut.
Laurie Stearn

1

dalam kasus saya, setel file cpp ke "C / C ++ compiler" di properti -> secara umum selesaikan kesalahan LNK2019.


0

Bagi saya bekerja, jika saya menambahkan baris di bawah ini di .vcxprojdalam itemGroupberkas cpp, yang terhubung ke file header.

<ClCompile Include="file.cpp" />

0

Dalam Visual Studio 2017 jika Anda ingin menguji anggota publik, cukup letakkan proyek nyata Anda dan uji proyek dalam solusi yang sama, dan tambahkan referensi ke proyek nyata Anda dalam proyek pengujian.

Lihat Pengujian Unit C ++ di Visual Studio dari blog MSDN untuk detail selengkapnya. Anda juga dapat memeriksa Write unit tests untuk C / C ++ di Visual Studio serta Gunakan Microsoft Unit Testing Framework untuk C ++ di Visual Studio , yang terakhir adalah jika Anda perlu menguji anggota non publik dan perlu melakukan pengujian dalam proyek yang sama sebagai kode asli Anda.

Perhatikan bahwa hal-hal yang ingin Anda uji perlu diekspor menggunakan __declspec(dllexport). Lihat Mengekspor dari DLL Menggunakan __declspec (dllexport) untuk detail selengkapnya.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.