Làm thế nào để giải quyết lỗi LNK2019: biểu tượng bên ngoài chưa được giải quyết - chức năng?


99

Tôi gặp lỗi này, nhưng tôi không biết làm thế nào để sửa chữa nó.

Tôi đang sử dụng Visual Studio 2013. Tôi đặt tên giải pháp là MyProjectTest Đây là cấu trúc của giải pháp thử nghiệm của tôi:

Cấu trúc

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

Tôi là người mới bắt đầu; đây là một chương trình đơn giản và nó chạy không có lỗi. Tôi đọc trên internet và bắt đầu quan tâm đến bài kiểm tra đơn vị, vì vậy tôi đã tạo một dự án thử nghiệm:

Tệp> Mới> Dự án ...> Đã cài đặt> Mẫu> Visual C ++> Kiểm tra> Dự án kiểm tra đơn vị bản địa>

Tên: UnitTest1 Giải pháp: Thêm vào giải pháp Sau đó, vị trí tự động chuyển sang đường dẫn của giải pháp đang mở hiện tại Đây là cấu trúc thư mục của giải pháp:

Cấu trúc thư mục

Tôi chỉ chỉnh sửa tệp 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
        }

    };
}

Nhưng tôi gặp lỗi LNK2019: ký hiệu bên ngoài chưa được giải quyết. Tôi biết rằng việc triển khai nhiều hàm bị thiếu. Tôi đã cố gắng xóa tệp function.cpp và tôi đã thay thế khai báo bằng định nghĩa và nó chạy. Nhưng việc viết cả khai báo và định nghĩa trong cùng một tệp không được khuyến khích. Làm thế nào tôi có thể sửa lỗi này mà không làm điều đó? Tôi có nên thay thế bằng #include "../MyProjectTest/function.cpp"trong tệp unittest.cpp không? (Tôi không giỏi tiếng Anh lắm. Cảm ơn)



6
HÃY CẨN THẬN Trong môi trường Windows , thư viện tĩnh có .LIBphần mở rộng tệp. Để làm phức tạp mọi thứ ... thư viện liên kết động (tức là *.DLL) có thể có một thư viện nhập đi kèm cũng có .LIBphần mở rộng tệp. Thư viện nhập này liệt kê tất cả các tiện ích được cung cấp bởi *.DLL. Để biết thêm thông tin, vui lòng đọc: Hướng dẫn dành cho người mới bắt đầu với người liên kết
Pressacco

4
Tại sao anh ta phải cẩn thận ??
Marshal craft

Câu trả lời:


80

Một tùy chọn sẽ là đưa function.cppvào UnitTest1dự án của bạn , nhưng đó có thể không phải là cấu trúc giải pháp lý tưởng nhất. Câu trả lời ngắn gọn cho vấn đề của bạn là khi xây dựng UnitTest1dự án của bạn , trình biên dịch và trình liên kết không có ý tưởng function.cpptồn tại và cũng không có liên kết nào chứa định nghĩa multiple. Một cách để khắc phục điều này là sử dụng liên kết các thư viện.

Vì các bài kiểm tra đơn vị của bạn nằm trong một dự án khác, tôi cho rằng ý định của bạn là làm cho dự án đó trở thành một chương trình kiểm tra đơn vị độc lập. Với các chức năng bạn đang thử nghiệm nằm trong một dự án khác, bạn có thể xây dựng dự án đó thành một thư viện được liên kết động hoặc tĩnh. Thư viện tĩnh được liên kết với các chương trình khác tại thời điểm xây dựng và có phần mở rộng .libvà các thư viện động được liên kết trong thời gian chạy và có phần mở rộng .dll. Đối với câu trả lời của tôi, tôi sẽ thích các thư viện tĩnh hơn.

Bạn có thể biến chương trình đầu tiên của mình thành một thư viện tĩnh bằng cách thay đổi nó trong các thuộc tính của dự án. Sẽ có một tùy chọn trong tab Chung nơi dự án được thiết lập để xây dựng thành tệp thực thi ( .exe). Bạn có thể thay đổi điều này thành .lib. Các .libtập tin sẽ xây dựng để cùng một vị trí như .exe.

Trong UnitTest1dự án của bạn , bạn có thể đi đến các thuộc tính của nó và trong tab Trình liên kết trong danh mục Thư mục Thư viện Bổ sung, hãy thêm đường dẫn đến các MyProjectTestbản dựng. Sau đó, đối với Phụ thuộc Bổ sung trong tab Trình liên kết - Đầu vào, hãy thêm tên thư viện tĩnh của bạn, rất có thể MyProjectTest.lib.

Điều đó sẽ cho phép dự án của bạn xây dựng. Lưu ý rằng bằng cách làm này, MyProjectTestsẽ không phải là một chương trình thực thi độc lập trừ khi bạn thay đổi các thuộc tính xây dựng của nó khi cần thiết, điều này sẽ ít hơn lý tưởng.


Trong 'Linker-> Tab Input', tôi phải đặt tiền tố '(OutDir)' cho thư viện tĩnh, đó là '$ (OutDir) MyProjectTest.lib', mặc dù vị trí của cả 'MyProject' và 'MyTestProject' được giữ trong cùng một thư mục gốc .
Pabitra Dash

13
Vì vậy, mỗi khi bạn muốn chạy các bài kiểm tra đơn vị, bạn nên chuyển đổi dự án testee của mình thành một thư viện tĩnh và mỗi khi bạn thực sự muốn chạy chương trình của mình, bạn chuyển đổi nó trở lại tệp thực thi, đây là giải pháp như thế nào?
A. Smoliak

1
Nếu MyProjectTest là một dll, chúng ta có thể kiểm tra nó không? Chúng tôi chỉ thêm nhập lib hay chúng tôi phải thêm các tệp obj?
aviit,

"Bạn có thể biến chương trình đầu tiên của mình thành một thư viện tĩnh bằng cách thay đổi nó trong các thuộc tính của dự án. Sẽ có một tùy chọn trong tab Chung, nơi dự án được đặt để xây dựng thành tệp thực thi (.exe). Bạn có thể thay đổi cài đặt này thành .lib . Tệp .lib sẽ xây dựng ở cùng một nơi với .exe "Làm điều này là đủ cho trường hợp của tôi. Phần còn lại đã được VS.
Ekrem Solmaz

39

Trong cây giải pháp Visual Studio, nhấp chuột phải vào dự án 'UnitTest1' rồi Thêm -> Mục hiện có -> chọn tệp ../MyProjectTest/ Chức năng.cpp


4
Lưu ý rằng (các) tệp thực tế không được sao chép hoặc chuyển đến ProjDir.
Laurie Stearn

Phương pháp này đã giải quyết các vấn đề tương tự xảy ra khi cố gắng thêm c ++ lib vào dự án CLI.
Deshan

17

Vì tôi muốn dự án của mình biên dịch thành EXE độc lập, tôi đã liên kết dự án UnitTest với tệp function.obj được tạo từ function.cpp và nó hoạt động. Nhấp chuột phải vào dự án 'UnitTest1'> Thuộc tính cấu hình> Trình liên kết> Đầu vào> Phụ thuộc bổ sung> thêm ".. \ MyProjectTest \ Debug \ function.obj"


1
Làm thế nào về trường hợp khi MyProjectTest là một dll? Bạn có thể thiết lập cho nó?
aviit

Nếu chúng ta có nhiều tệp obj. chúng ta có thể thêm một số thứ như thế này * .obj không? Giải pháp của bạn đã làm việc với tôi nhưng tôi không muốn thêm mọi tệp obj mới theo cách thủ công.
aviit,

10

Tôi vừa gặp sự cố này trong Visual Studio 2013. Rõ ràng bây giờ, có hai dự án trong cùng một giải pháp và thiết lập các phụ thuộc là không đủ. Bạn cần thêm tham chiếu dự án giữa chúng. Để làm việc đó:

  1. Nhấp chuột phải vào dự án trong khám phá giải pháp
  2. Nhấp vào Thêm => Tham khảo ...
  3. Nhấp vào nút Thêm tài liệu tham khảo mới
  4. Chọn hộp cho các dự án mà dự án này dựa vào
  5. Bấm OK

Ý bạn là gì khi thiết lập các phụ thuộc? Tôi đã thêm tài liệu tham khảo nhưng nó vẫn bị phàn nàn. devblogs.microsoft.com/cppblog/cpp-testing-in-visual-studio đề xuất điều đó là đủ.
tschumann 30/07/19

8

hóa ra tôi đang sử dụng tệp .c với tệp .cpp. đổi tên .c thành .cpp đã giải quyết được vấn đề của tôi.


6

Một cách khác mà bạn có thể gặp phải lỗi trình liên kết này (như tôi đã từng xảy ra) là nếu bạn đang xuất một thể hiện của một lớp từ một dll nhưng chưa khai báo chính lớp đó là nhập / xuất.

 #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

Vì vậy, mặc dù chủ yếu tôi chỉ xuất một thể hiện của lớp Sách được gọi bookở trên, tôi phải khai báo Booklớp là lớp xuất / nhập cũng như việc gọi book.WordCount()trong dll khác gây ra lỗi liên kết.


2

Điều này đã xảy ra với tôi nên tôi nghĩ tôi có thể chia sẻ giải pháp của mình, đơn giản như sau:

Kiểm tra Bộ ký tự của cả hai dự án trong Thuộc tính cấu hình -> Chung -> Bộ ký tự

Dự án UnitTest của tôi đã sử dụng Bộ ký tự mặc định Multi-Byte trong khi tôi thích ở trong Unicode .
Hàm của tôi đang sử dụng TCHAR làm tham số. Kết quả là trong lib của tôi, TCHAR của tôi đã được chuyển thành WCHAR nhưng nó là một ký tự * trên UnitTest của tôi: biểu tượng khác vì cuối cùng các thông số thực sự không giống nhau.


1

Tôi vừa phát hiện ra điều đó LNK2019xảy ra trong quá trình biên dịch trong Visual Studio 2015 nếu quên cung cấp định nghĩa cho một hàm đã khai báo bên trong một lớp.

Lỗi trình liên kết rất khó hiểu nhưng tôi đã thu hẹp những gì còn thiếu bằng cách đọc qua lỗi và cung cấp định nghĩa bên ngoài lớp để xóa điều này.


Vấn đề trong một số trường hợp là các tiêu đề có chứa các định dạng lớp đều được tham chiếu / bao gồm độc đáo nhưng các cpp tương ứng của chúng có thể không được cung cấp cho trình liên kết. Cách tốt nhất để kiểm tra là lướt qua các phụ thuộc bên ngoài của dự án trong Solution Explorer. Tuy nhiên, sẽ có lợi cho VS nếu đưa ra một số loại cảnh báo về sự tồn tại / bao gồm tệp liên quan đến lỗi.
Laurie Stearn

1

trong trường hợp của tôi, hãy đặt tệp cpp thành "Trình biên dịch C / C ++" trong thuộc tính -> giải quyết chung lỗi LNK2019.


0

Đối với tôi làm việc, nếu tôi thêm dòng dưới đây trong .vcxprojtrong itemGrouptập tin cpp, được kết nối với tập tin tiêu đề.

<ClCompile Include="file.cpp" />

0

Trong Visual Studio 2017, nếu bạn muốn kiểm tra các thành viên công khai, chỉ cần đặt dự án thực và dự án thử nghiệm của bạn trong cùng một giải pháp và thêm tham chiếu đến dự án thực của bạn trong dự án thử nghiệm.

Xem Kiểm tra đơn vị C ++ trong Visual Studio từ blog MSDN để biết thêm chi tiết. Bạn cũng có thể kiểm tra Viết bài kiểm tra đơn vị cho C / C ++ trong Visual Studio cũng như Sử dụng Khung kiểm tra đơn vị của Microsoft cho C ++ trong Visual Studio , sau này nếu bạn cần kiểm tra không phải thành viên công khai và cần đặt các bài kiểm tra trong cùng một dự án như mã thực của bạn.

Lưu ý rằng những thứ bạn muốn kiểm tra sẽ cần được xuất bằng cách sử dụng __declspec(dllexport). Xem Xuất từ ​​DLL bằng __declspec (dllexport) để biết thêm chi tiết.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.