LNK2019 hatası nasıl çözülür: çözülmemiş harici sembol - fonksiyon?


101

Bu hatayı alıyorum ama nasıl düzelteceğimi bilmiyorum.

Visual Studio 2013 kullanıyorum. Çözüm adını MyProjectTest yaptım Bu benim test çözümümün yapısı:

Yapı

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

Acemiyim; bu basit bir programdır ve hatasız çalışır. İnternette okudum ve ünite testiyle ilgilenmeye başladım, bu yüzden bir test projesi oluşturdum:

Dosya> Yeni> Proje ...> Yüklendi> Şablonlar> Visual C ++> Test> Yerel Birim Test Projesi>

Ad: UnitTest1 Çözüm: Çözüme ekle Daha sonra konum, geçerli açık çözümün yoluna otomatik olarak değiştirildi Bu, çözümün klasör yapısıdır:

Klasör yapısı

Sadece unittest1.cpp dosyasını düzenledim:

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

    };
}

Ancak LNK2019 hatası alıyorum: çözülmemiş harici sembol. Çoklu fonksiyon uygulamasının eksik olduğunu biliyorum . Function.cpp dosyasını silmeye çalıştım ve bildirimi tanımla değiştirdim ve çalıştırdım. Ancak hem beyanı hem de tanımı aynı dosyaya yazmanız önerilmez. Bunu yapmadan bu hatayı nasıl düzeltebilirim? #include "../MyProjectTest/function.cpp"Unittest.cpp dosyasında değiştirmeli miyim ? (İngilizcede pek iyi değilim. Teşekkürler)



6
CAREFUL bir de , Windows ortamında, statik kütüphaneler bir var .LIBdosya uzantısı. İşleri karmaşıklaştırmak için ... dinamik bağlantı kitaplıkları (yani *.DLL) , bir dosya uzantısına sahip eşlik eden bir içe aktarma kitaplığına sahip olabilir .LIB. Bu içe aktarma kitaplığı, .tarafından sağlanan tüm ürünleri listeler *.DLL. Daha fazla bilgi için lütfen şunu okuyun: Beginner's Guide to
Linkers

5
Neden dikkatli olmalı?
mareşal gemisi

Yanıtlar:


83

Seçeneklerden biri dahil etmek olurdu function.cppsenin içinde UnitTest1proje, ama bu en ideal çözüm yapısı olmayabilir. Probleminizin kısa cevabı, UnitTest1projenizi oluştururken, derleyici ve bağlayıcının var olan hiçbir fikrinin olmaması function.cppve ayrıca bir tanımını içeren bağlanacak hiçbir şeyin olmamasıdır multiple. Bunu düzeltmenin bir yolu, kitaplıkları bağlamayı kullanmaktır.

Birim testleriniz farklı bir projede olduğundan, niyetinizin bu projeyi bağımsız bir birim test programı yapmak olduğunu varsayıyorum. Başka bir projede bulunan test ettiğiniz işlevlerle, bu projeyi dinamik veya statik olarak bağlantılı bir kitaplıkta oluşturmak mümkündür. Statik kitaplıklar, derleme zamanında diğer programlara bağlanır ve uzantıya sahiptir .libve dinamik kitaplıklar çalışma zamanında bağlanır ve uzantıya sahiptir .dll. Cevabım için statik kitaplıkları tercih edeceğim.

İlk programınızı proje özelliklerinde değiştirerek statik bir kitaplığa dönüştürebilirsiniz. Genel sekmesinin altında, projenin çalıştırılabilir ( .exe) oluşturacak şekilde ayarlandığı bir seçenek olmalıdır . Bunu olarak değiştirebilirsiniz .lib. .libDosya aynı yere inşa edecek .exe.

Senin içinde UnitTest1proje, onun özelliklerine gidebilir ve kategori Ek Kütüphane Dizinler içinde Bağlayıcı sekmesi altında, hangi yolu ekleyin MyProjectTestoluşturur. Ardından, Bağlayıcı - Giriş sekmesi altındaki Ek Bağımlılıklar için, büyük olasılıkla statik kitaplığınızın adını ekleyin MyProjectTest.lib.

Bu, projenizin inşa edilmesine izin vermelidir. Bunu yaparak MyProjectTest, yapı özelliklerini gerektiği gibi değiştirmediğiniz sürece tek başına çalıştırılabilir bir program olmayacağını unutmayın, bu idealden daha az olacaktır.


'Bağlayıcı-> Giriş Sekmesi'nde, statik kitaplık için' (OutDir) 'önekini almak zorunda kaldım, yani' $ (OutDir) MyProjectTest.lib ', ancak hem' MyProject 'hem de' MyTestProject 'konumu aynı kök klasörde tutuluyor .
Pabitra Dash

15
Öyleyse, birim testleri çalıştırmak istediğiniz her seferinde, sınanan projenizi statik bir kitaplığa dönüştürmelisiniz ve programınızı gerçekten çalıştırmak istediğiniz her seferinde onu bir yürütülebilir dosyaya dönüştürürsünüz, bu nasıl bir çözüm olur?
A. Smoliak

1
MyProjectTest bir dll ise, test edebilir miyiz? Sadece içe aktarma kütüphanesini mi ekliyoruz yoksa obj dosyalarını mı eklemeliyiz?
aviit

"İlk programınızı proje özelliklerinde değiştirerek statik bir kitaplığa dönüştürebilirsiniz. Genel sekmesinin altında projenin çalıştırılabilir (.exe) oluşturacak şekilde ayarlandığı bir seçenek olmalıdır. Bunu .lib olarak değiştirebilirsiniz. .Lib dosyası .exe ile aynı yere inşa edilecek "Bunu yapmak benim durumum için yeterliydi. Gerisi zaten VS tarafından ele alındı.
Ekrem Solmaz

39

Visual Studio çözüm ağacında 'UnitTest1' projesine sağ tıklayın ve ardından Ekle -> Mevcut öğe -> dosyayı seçin ../MyProjectTest/function.cpp


4
Gerçek dosyaların ProjDir'e kopyalanmadığını veya taşınmadığını unutmayın.
Laurie Stearn

Bu yöntem, bir CLI projesine c ++ lib eklemeye çalışırken meydana gelen benzer sorunları çözdü.
Deshan

17

Projemin bağımsız bir EXE'de derlenmesini istediğim için, UnitTest projesini function.cpp'den oluşturulan function.obj dosyasına bağladım ve çalışıyor. 'UnitTest1' projesine sağ tıklayın> Yapılandırma Özellikleri> Bağlayıcı> Giriş> Ek Bağımlılıklar> ".. \ ProjemTest \ Debug \ function.obj" ekleyin


1
MyProjectTest'in bir dll olduğu duruma ne dersiniz? Ayarlayabilir misin?
aviit

Çok sayıda obj dosyamız varsa. bunun gibi bir şey ekleyebilir miyiz * .obj? Çözümünüz benimle çalıştı ancak her yeni obj dosyasını manuel olarak eklemek istemiyorum.
aviit

10

Visual Studio 2013'te bu problemle karşılaştım. Görünüşe göre şimdi aynı çözümde iki projeye sahip olmak ve bağımlılıkları ayarlamak yeterli değil. Aralarına bir proje referansı eklemeniz gerekir. Bunu yapmak için:

  1. Çözüm araştırmasında projeye sağ tıklayın
  2. Ekle => Referanslar ... 'ı tıklayın.
  3. Yeni Referans Ekle düğmesini tıklayın
  4. Bu projenin dayandığı projelerin kutularını işaretleyin
  5. Tamam'ı tıklayın

Bağımlılıkları belirlemekle ne demek istiyorsun? Referansı ekledim ama yine de şikayet etti. devblogs.microsoft.com/cppblog/cpp-testing-in-visual-studio bunun yeterli olacağını önerdi.
tschumann

8

.c dosyalarını .cpp dosyalarıyla kullandığım ortaya çıktı. .c'yi .cpp olarak yeniden adlandırmak sorunumu çözdü.


6

Bu linker hatasını almanın başka bir yolu (benim olduğu gibi), bir dll'den bir sınıfın örneğini dışa aktarıyorsanız, ancak bu sınıfın kendisini içe / dışa aktarma olarak bildirmediyseniz.

 #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

Dolayısıyla, öncelikle yukarıda adı verilen Book sınıfının yalnızca bir örneğini dışa aktarıyor olsam da book, Booksınıfı dışa aktarma / içe aktarma sınıfı olarak bildirmek zorunda kaldım ve aksi takdirde book.WordCount()diğer dll'de arama yapmak bir bağlantı hatasına neden oluyordu.


3

Bu benim başıma geldi, bu yüzden çözümümü paylaşabileceğimi düşündüm, olduğu kadar basit:

Yapılandırma Özellikleri -> Genel -> Karakter Kümesi'nde her iki projenin Karakter Kümesini kontrol edin.

Benim UnitTest projem varsayılan Karakter Kümesi Multi-Byte'ı kullanırken kütüphanelerim Unicode'da .
Benim fonksiyonum parametre olarak bir TCHAR kullanıyordu . Benim lib sonucunda benim TCHAR edildi dönüştürülmüş bir içine WCHAR ama oldu Char * benim UnitTest tarih: parametreler sonunda gerçekten aynı olmadığı için sembol farklıydı.


Teşekkürler, sorunu
çözmeme

1

LNK2019Bir sınıf içinde bildirilmiş bir işlev için bir tanım sağlamayı unutursam, Visual Studio 2015'te derleme sırasında bunun gerçekleştiğini keşfettim .

Bağlayıcı hatası oldukça gizemliydi, ancak hatayı okuyarak eksik olanı daralttım ve bunu temizlemek için sınıfın dışında tanım sağladım.


Bazı durumlarda sorun, sınıf tanımlarını içeren başlıkların hepsine güzel bir şekilde atıfta bulunulması / dahil edilmesidir, ancak bunların karşılık gelen cpps'leri bağlayıcıya sunulmayabilir . Kontrol etmenin en iyi yolu, Çözüm Gezgini'nde proje dış bağımlılıklarına göz atmaktır. Bununla birlikte, VS'nin hatayla ilgili bir tür dosya varlığı / dahil etme uyarısı yayınlaması yararlı olacaktır.
Laurie Stearn

1

benim durumumda, cpp dosyasını "C / C ++ derleyici" olarak ayarlayın -> genel olarak LNK2019 hatasını çözün.


0

Ben bu hat feryat eklerseniz Benim için çalışıyor .vcxprojiçinde itemGroupbaşlık dosyasına bağlanır cpp dosyası.

<ClCompile Include="file.cpp" />

0

Visual Studio 2017'de genel üyeleri test etmek istiyorsanız, gerçek projenizi ve test projenizi aynı çözüme koyun ve test projesinde gerçek projenize bir referans ekleyin.

Daha fazla ayrıntı için MSDN blogundan Visual Studio'da C ++ Birim Testi konusuna bakın . Ayrıca kontrol edebilirsiniz Visual Studio C / C ++ için Yaz birim testleri yanı sıra Visual Studio Kullanılmak C için Microsoft Birim Test Çerçevesi ++ tükenen olmayan kamu üyeleri ve aynı projede testleri koymak gereğini test etmek gerekirse gerçek kodunuz olarak.

Test etmek istediğiniz şeylerin kullanılarak dışa aktarılması gerekeceğini unutmayın __declspec(dllexport). Daha fazla ayrıntı için __declspec (dllexport) Kullanarak DLL'den Dışa Aktarma konusuna bakın .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.