วิธีแก้ข้อผิดพลาด LNK2019: สัญลักษณ์ภายนอกที่ไม่ได้รับการแก้ไข - ฟังก์ชัน


103

ฉันได้รับข้อผิดพลาดนี้ แต่ไม่รู้วิธีแก้ไข

ฉันใช้ Visual Studio 2013 ฉันตั้งชื่อโซลูชันว่าMyProjectTest นี่คือโครงสร้างของโซลูชันการทดสอบของฉัน:

โครงสร้าง

- ฟังก์ชั่น 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;
}

ฉันเป็นมือใหม่ นี่เป็นโปรแกรมง่ายๆและทำงานโดยไม่มีข้อผิดพลาด ฉันอ่านในอินเทอร์เน็ตและเริ่มสนใจการทดสอบหน่วยการเรียนรู้ดังนั้นฉันจึงสร้างโครงการทดสอบ:

ไฟล์> ใหม่> โครงการ ... > ติดตั้ง> เทมเพลต> Visual C ++> ทดสอบ> โครงการทดสอบหน่วยดั้งเดิม>

ชื่อ: โซลูชันUnitTest1 : เพิ่มลงในโซลูชัน จากนั้นตำแหน่งจะเปลี่ยนไปยังเส้นทางของโซลูชันที่เปิดอยู่โดยอัตโนมัตินี่คือโครงสร้างโฟลเดอร์ของโซลูชัน:

โครงสร้างโฟลเดอร์

ฉันแก้ไขเฉพาะไฟล์ 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
        }

    };
}

แต่ฉันได้รับข้อผิดพลาด LNK2019: สัญลักษณ์ภายนอกที่ไม่ได้รับการแก้ไข ฉันรู้ว่าไม่มีการนำฟังก์ชันหลายไปใช้งาน ฉันพยายามลบไฟล์ function.cpp และฉันแทนที่การประกาศด้วยนิยามและมันก็ทำงาน แต่ไม่แนะนำให้เขียนทั้งคำประกาศและคำจำกัดความในไฟล์เดียวกัน ฉันจะแก้ไขข้อผิดพลาดนี้โดยไม่ทำเช่นนั้นได้อย่างไร ฉันควรแทนที่ด้วย#include "../MyProjectTest/function.cpp"ไฟล์ unittest.cpp หรือไม่ (ฉันไม่เก่งภาษาอังกฤษมากขอบคุณ)



7
ระวังในสภาพแวดล้อมWindowsไลบรารีแบบคงที่มี.LIBนามสกุลไฟล์ เพื่อทำให้สิ่งต่างๆซับซ้อน ... ไลบรารีลิงก์แบบไดนามิก (เช่น*.DLL) สามารถมีไลบรารีนำเข้าประกอบซึ่งมี.LIBนามสกุลไฟล์ด้วย ไลบรารีนำเข้านี้แสดงรายการสินค้าทั้งหมดที่มีให้โดยไฟล์*.DLL. สำหรับข้อมูลเพิ่มเติมโปรดอ่าน: Beginner's Guide to Linkers
Pressacco

7
ทำไมเขาต้องระวัง ??
ยานจอมพล

คำตอบ:


84

ทางเลือกหนึ่งคือรวมfunction.cppไว้ในUnitTest1โครงการของคุณแต่นั่นอาจไม่ใช่โครงสร้างโซลูชันที่ดีที่สุด คำตอบสั้น ๆ สำหรับปัญหาของคุณคือเมื่อสร้างUnitTest1โครงการของคุณคอมไพลเลอร์และตัวเชื่อมโยงไม่มีความคิดที่function.cppมีอยู่และไม่มีอะไรเชื่อมโยงที่มีคำจำกัดความของmultiple. วิธีแก้ไขปัญหานี้คือการใช้ลิงก์ไลบรารี

เนื่องจากการทดสอบหน่วยของคุณอยู่ในโครงการอื่นฉันจึงถือว่าคุณตั้งใจจะทำให้โครงการนั้นเป็นโปรแกรมทดสอบหน่วยแบบสแตนด์อโลน ด้วยฟังก์ชันที่คุณกำลังทดสอบที่อยู่ในโปรเจ็กต์อื่นคุณสามารถสร้างโปรเจ็กต์นั้นไปยังไลบรารีที่ลิงก์แบบไดนามิกหรือแบบสแตติก ห้องสมุดแบบคงที่มีการเชื่อมโยงกับโปรแกรมอื่น ๆ เวลาที่สร้างและมีการขยายและห้องสมุดแบบไดนามิกที่มีการเชื่อมโยงที่รันไทม์และมีนามสกุลเป็น.lib .dllสำหรับคำตอบของฉันฉันจะชอบไลบรารีแบบคงที่

คุณสามารถเปลี่ยนโปรแกรมแรกของคุณให้เป็นไลบรารีแบบคงที่ได้โดยเปลี่ยนในคุณสมบัติโปรเจ็กต์ ควรมีตัวเลือกภายใต้แท็บทั่วไปที่โครงการถูกตั้งค่าให้สร้างเป็นปฏิบัติการ ( .exe) .libคุณสามารถเปลี่ยนนี้ ไฟล์จะสร้างไปยังสถานที่เช่นเดียวกับ.lib.exe

ในUnitTest1โปรเจ็กต์ของคุณคุณสามารถไปที่คุณสมบัติของโปรเจ็กต์และภายใต้แท็บ Linker ในหมวดหมู่ไดเร็กทอรีไลบรารีเพิ่มเติมให้เพิ่มพา ธ ที่จะMyProjectTestสร้าง แล้วสำหรับการอ้างอิงเพิ่มเติมภายใต้ linker - MyProjectTest.libแท็บป้อนข้อมูลเพิ่มชื่อของห้องสมุดคงที่ของคุณมากที่สุด

ซึ่งจะช่วยให้โครงการของคุณสามารถสร้างได้ โปรดทราบว่าการทำเช่นนี้MyProjectTestจะไม่เป็นโปรแกรมปฏิบัติการแบบสแตนด์อโลนเว้นแต่คุณจะเปลี่ยนคุณสมบัติการสร้างตามต้องการซึ่งจะน้อยกว่าในอุดมคติ


ใน 'Linker-> Input Tab' ฉันต้องนำหน้า '(OutDir)' สำหรับไลบรารีแบบคงที่นั่นคือ '$ (OutDir) MyProjectTest.lib' แม้ว่าตำแหน่งของทั้ง 'MyProject' และ 'MyTestProject' จะเก็บไว้ในโฟลเดอร์รูทเดียวกัน .
Pabitra Dash

16
ดังนั้นทุกครั้งที่คุณต้องการเรียกใช้การทดสอบหน่วยคุณควรแปลงโครงการ testee ของคุณเป็นไลบรารีแบบคงที่และทุกครั้งที่คุณต้องการเรียกใช้โปรแกรมของคุณคุณจะแปลงกลับเป็นปฏิบัติการได้อย่างไรวิธีแก้ปัญหานี้คืออะไร?
อ. Smoliak

1
ถ้า MyProjectTest เป็น dll เราจะทดสอบได้ไหม เราแค่เพิ่มนำเข้า lib หรือเราต้องเพิ่มไฟล์ obj?
aviit

"คุณสามารถเปลี่ยนโปรแกรมแรกของคุณให้เป็นไลบรารีแบบคงที่ได้โดยการเปลี่ยนในคุณสมบัติของโปรเจ็กต์ควรมีตัวเลือกอยู่ใต้แท็บทั่วไปที่โปรเจ็กต์ถูกตั้งค่าให้สร้างเป็นไฟล์ปฏิบัติการ (.exe) คุณสามารถเปลี่ยนเป็น. lib ไฟล์. lib จะสร้างที่เดียวกับ. exe "การทำเช่นนี้เพียงพอสำหรับกรณีของฉัน ส่วนที่เหลือได้รับการจัดการโดย VS.
Ekrem Solmaz

39

ในแผนผังโซลูชัน Visual Studio คลิกขวาที่โครงการ 'UnitTest1' จากนั้นเพิ่ม -> รายการที่มีอยู่ -> เลือกไฟล์ ../MyProjectTest/function.cpp


4
โปรดสังเกตว่าไฟล์จริงไม่ได้ถูกคัดลอกหรือย้ายไปที่ ProjDir
Laurie Stearn

วิธีนี้แก้ไขปัญหาที่คล้ายกันที่เกิดขึ้นขณะพยายามเพิ่ม c ++ lib ในโปรเจ็กต์ CLI
Deshan

17

เนื่องจากฉันต้องการให้โปรเจ็กต์ของฉันคอมไพล์เป็น EXE แบบสแตนด์อโลนฉันจึงเชื่อมโยงโปรเจ็กต์ UnitTest กับไฟล์ function.obj ที่สร้างจาก function.cpp และใช้งานได้ คลิกขวาที่โครงการ 'UnitTest1'> Configuration Properties> Linker> Input> Additional Dependencies> add ".. \ MyProjectTest \ Debug \ function.obj"


1
แล้วกรณีที่ MyProjectTest เป็น dll ล่ะ? คุณสามารถตั้งค่าได้หรือไม่?
aviit

หากเรามีไฟล์ obj จำนวนมาก เราสามารถเพิ่มสิ่งนี้ * .obj ได้ไหม โซลูชันของคุณใช้ได้กับฉัน แต่ฉันไม่ต้องการเพิ่มไฟล์ obj ใหม่ทุกไฟล์ด้วยตนเอง
aviit

10

ฉันเพิ่งพบปัญหานี้ใน Visual Studio 2013 เห็นได้ชัดว่าตอนนี้มีสองโปรเจ็กต์ในโซลูชันเดียวกันและการตั้งค่าการอ้างอิงนั้นไม่เพียงพอ คุณต้องเพิ่มการอ้างอิงโครงการระหว่างพวกเขา ในการทำเช่นนั้น:

  1. คลิกขวาที่โครงการในการสำรวจโซลูชัน
  2. คลิกเพิ่ม => การอ้างอิง ...
  3. คลิกปุ่มเพิ่มการอ้างอิงใหม่
  4. ทำเครื่องหมายในช่องสำหรับโครงการที่โครงการนี้อาศัยอยู่
  5. คลิกตกลง

1
คุณหมายถึงอะไรเมื่อตั้งค่าการอ้างอิง? ฉันเพิ่มข้อมูลอ้างอิง แต่ก็ยังบ่น devblogs.microsoft.com/cppblog/cpp-testing-in-visual-studioแนะนำว่าจะเพียงพอ
tschumann

8

ปรากฎว่าฉันใช้ไฟล์. c กับไฟล์. cpp การเปลี่ยนชื่อ. c เป็น. cpp ช่วยแก้ปัญหาของฉันได้


6

อีกวิธีหนึ่งที่คุณจะได้รับข้อผิดพลาดตัวเชื่อมโยงนี้ (เหมือนที่ฉันเคยเป็น) คือถ้าคุณกำลังเอ็กซ์พอร์ตอินสแตนซ์ของคลาสจาก dll แต่ไม่ได้ประกาศคลาสนั้นว่าเป็นอิมพอร์ต / เอ็กซ์พอร์ต

 #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

ดังนั้นแม้ว่าโดยหลักแล้วฉันจะส่งออกเพียงอินสแตนซ์ของคลาสหนังสือที่เรียกbookข้างบน แต่ฉันต้องประกาศBookคลาสเป็นคลาสส่งออก / นำเข้าเช่นกันมิฉะนั้นการเรียกbook.WordCount()ใน dll อื่นก็ทำให้เกิดข้อผิดพลาดในการเชื่อมโยง


3

สิ่งนี้เกิดขึ้นกับฉันดังนั้นฉันจึงคิดว่าฉันอาจแบ่งปันวิธีแก้ปัญหาของฉันง่ายๆเหมือนเดิม:

ตรวจสอบชุดอักขระของทั้งสองโครงการในคุณสมบัติการกำหนดค่า -> ทั่วไป ->ชุดอักขระ

โครงการ UnitTest ของฉันใช้ชุดอักขระเริ่มต้น Multi-Byteขณะ libs ของฉันที่ในUnicode
ฟังก์ชันของฉันใช้TCHARเป็นพารามิเตอร์ เป็นผลให้ lib ของฉันTCHARของฉันถูกเปลี่ยนเป็นWCHARแต่มันเป็นถ่าน *บน UnitTest ของฉัน: สัญลักษณ์ต่างกันเพราะพารามิเตอร์ไม่เหมือนกันในตอนท้าย


1

ฉันเพิ่งค้นพบว่า LNK2019เกิดขึ้นระหว่างการคอมไพล์ใน Visual Studio 2015 หากลืมระบุคำจำกัดความสำหรับฟังก์ชันที่ประกาศไว้ภายในคลาส

ข้อผิดพลาดของตัวเชื่อมโยงเป็นความลับอย่างมาก แต่ฉัน จำกัด สิ่งที่ขาดหายไปให้แคบลงโดยการอ่านข้อผิดพลาดและให้คำจำกัดความนอกคลาสเพื่อล้างสิ่งนี้


ปัญหาในบางกรณีคือส่วนหัวที่มีคลาส defs จะถูกอ้างอิง / รวมไว้อย่างดี แต่ cpps ที่เกี่ยวข้องอาจไม่พร้อมใช้งานสำหรับตัวเชื่อมโยง วิธีที่ดีที่สุดในการตรวจสอบคือการปัดผ่านการอ้างอิงภายนอกของโครงการใน Solution Explorer มันจะเป็นประโยชน์สำหรับ VS ในการออกคำเตือนการมีอยู่ / การรวมไฟล์บางประเภทเกี่ยวกับข้อผิดพลาด
Laurie Stearn

1

ในกรณีของฉันตั้งค่าไฟล์ cpp เป็น "คอมไพเลอร์ C / C ++" ในคุณสมบัติ -> ทั่วไปแก้ไขข้อผิดพลาด LNK2019


0

สำหรับผมทำงานถ้าฉันจะเพิ่มการร้องในบรรทัดนี้.vcxprojในitemGroupไฟล์ CPP ซึ่งจะเชื่อมต่อกับไฟล์ส่วนหัว

<ClCompile Include="file.cpp" />

0

ใน Visual Studio 2017 หากคุณต้องการทดสอบสมาชิกสาธารณะเพียงใส่โครงการจริงและโครงการทดสอบของคุณในโซลูชันเดียวกันและเพิ่มการอ้างอิงไปยังโครงการจริงของคุณในโครงการทดสอบ

ดูการทดสอบหน่วย C ++ ใน Visual Studioจากบล็อก MSDN สำหรับรายละเอียดเพิ่มเติม คุณยังสามารถตรวจสอบเขียนการทดสอบหน่วยสำหรับ C / C ++ ใน Visual Studioรวมทั้งใช้ Microsoft Unit Testing Framework สำหรับ C ++ ใน Visual Studio ได้อีกด้วยซึ่งหากคุณต้องการทดสอบสมาชิกที่ไม่ใช่สาธารณะและต้องทำการทดสอบในโครงการเดียวกัน เป็นรหัสจริงของคุณ

หมายเหตุ: __declspec(dllexport)สิ่งที่คุณต้องการในการทดสอบจะต้องมีการส่งออกโดยใช้ ดูการส่งออกจาก DLL โดยใช้ __declspec (dllexport)สำหรับรายละเอียดเพิ่มเติม

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.