Как решить ошибку LNK2019: неразрешенный внешний символ - функция?

100

Я получаю эту ошибку, но не знаю, как ее исправить.

Я использую Visual Studio 2013. Я назвал решение MyProjectTest. Это структура моего тестового решения:

Структура

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

Я новичок; это простая программа, работающая без ошибок. Я прочитал в Интернете и заинтересовался модульным тестом, поэтому я создал тестовый проект:

Файл> Создать> Проект ...> Установлено> Шаблоны> 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: неразрешенный внешний символ. Я знаю, что реализация функции multiple отсутствует. Я попытался удалить файл function.cpp, заменил объявление определением, и он запустился. Но записывать декларацию и определение в одном файле не рекомендуется. Как я могу исправить эту ошибку без этого? Должен ли я заменить на#include "../MyProjectTest/function.cpp" в файле unittest.cpp на? (Я не очень хорошо говорю по-английски. Спасибо)

phibao37
источник
6
БУДЬТЕ ОСТОРОЖНЫ В среде Windows статические библиотеки имеют .LIBрасширение файла. Чтобы усложнить ситуацию ... библиотеки динамической компоновки (т.е. *.DLL) могут иметь сопутствующую библиотеку импорта, которая также имеет .LIBрасширение файла. В этой библиотеке импорта перечислены все преимущества, предоставляемые *.DLL. Для получения дополнительной информации, пожалуйста, прочтите: Руководство для начинающих по
линкерам
5
Почему он должен быть осторожным ??
marshal craft

Ответы:

81

Один из вариантов - включить его function.cppв ваш UnitTest1проект, но это может быть не самая идеальная структура решения. Короткий ответ на вашу проблему заключается в том, что при создании вашего UnitTest1проекта компилятор и компоновщик понятия не имеют, что function.cppсуществует, а также не имеют ничего для ссылки, содержащей определение multiple. Способ исправить это - использовать линковочные библиотеки.

Поскольку ваши модульные тесты находятся в другом проекте, я предполагаю, что вы намерены сделать этот проект отдельной программой модульного тестирования. С тестируемыми функциями, расположенными в другом проекте, можно построить этот проект в динамически или статически подключаемой библиотеке. Статические библиотеки связаны с другими программами во время сборки и имеют расширение .lib, а динамические библиотеки подключаются во время выполнения и имеют расширение .dll. В качестве ответа я предпочитаю статические библиотеки.

Вы можете превратить вашу первую программу в статическую библиотеку, изменив ее в свойствах проекта. На вкладке «Общие» должна быть опция, в которой проект настроен на сборку в исполняемый файл ( .exe). Вы можете изменить это на .lib. .libФайл будет строить на то же место, что и .exe.

В своем UnitTest1проекте вы можете перейти к его свойствам и на вкладке «Компоновщик» в категории «Дополнительные каталоги библиотеки» добавить путь, по которому выполняется MyProjectTestсборка. Затем для дополнительных зависимостей на вкладке Linker - Input, скорее всего, добавьте имя своей статической библиотеки MyProjectTest.lib.

Это должно позволить вашему проекту построить. Обратите внимание, что в результате этого MyProjectTestпрограмма не будет автономной исполняемой, если вы не измените ее свойства сборки по мере необходимости, что было бы не идеально.

кевинтодиско
источник
В 'Linker-> Input Tab' мне пришлось поставить префикс '(OutDir)' для статической библиотеки, то есть '$ (OutDir) MyProjectTest.lib', хотя расположение обоих 'MyProject' и 'MyTestProject' хранится в одной корневой папке .
Пабитра Даш
14
Итак, каждый раз, когда вы хотите запускать модульные тесты, вы должны преобразовывать свой тестируемый проект в статическую библиотеку, и каждый раз, когда вы действительно хотите запустить свою программу, вы конвертируете ее обратно в исполняемый файл, как это решение?
А. Смоляк
1
Если MyProjectTest - это dll, можем ли мы ее протестировать? Мы просто добавляем импортную библиотеку или мы должны добавить файлы obj?
aviit
«Вы можете превратить свою первую программу в статическую библиотеку, изменив ее в свойствах проекта. На вкладке« Общие »должна быть опция, в которой проект настроен на сборку в исполняемый файл (.exe). Вы можете изменить его на .lib .Lib-файл будет построен в том же месте, что и .exe "В моем случае этого было достаточно. Остальное уже было обработано VS.
Экрем Солмаз,
39

В дереве решений Visual Studio щелкните правой кнопкой мыши проект «UnitTest1», затем «Добавить» -> «Существующий элемент» -> выберите файл ../MyProjectTest/function.cpp

Нияз Иванов
источник
4
Обратите внимание, что фактические файлы не копируются и не перемещаются в ProjDir.
Laurie Stearn,
Этот метод решил аналогичные проблемы, возникающие при попытке добавить c ++ lib в проект CLI.
Deshan
17

Поскольку я хочу, чтобы мой проект компилировался в автономный EXE-файл, я связал проект UnitTest с файлом function.obj, созданным из function.cpp, и он работает. Щелкните правой кнопкой мыши проект «UnitTest1»> Свойства конфигурации> Компоновщик> Вход> Дополнительные зависимости> добавьте «.. \ MyProjectTest \ Debug \ function.obj»

Гарригг
источник
1
Как насчет случая, когда MyProjectTest - это dll? Вы можете настроить его?
aviit
Если у нас много obj file. мы можем добавить что-нибудь вроде этого * .obj? Ваше решение работало со мной, но я не хочу вручную добавлять все новые файлы obj.
aviit
10

Я только что столкнулся с этой проблемой в Visual Studio 2013. По-видимому, теперь недостаточно иметь два проекта в одном решении и установить зависимости. Между ними нужно добавить ссылку на проект. Для этого:

  1. Щелкните правой кнопкой мыши проект в решении изучить
  2. Нажмите Добавить => Ссылки ...
  3. Нажмите кнопку Добавить новую ссылку
  4. Установите флажки для проектов, на которых основан этот проект.
  5. Нажмите ОК
Кевин Дилл
источник
Что вы подразумеваете под установкой зависимостей? Я добавил ссылку, но она все равно жаловалась. devblogs.microsoft.com/cppblog/cpp-testing-in-visual-studio предположил, что этого будет достаточно.
tschumann
8

оказалось, что я использовал файлы .c с файлами .cpp. переименование .c в .cpp решило мою проблему.

Cahit Beyaz
источник
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класс как класс экспорта / импорта, а в противном случае вызов book.WordCount()другой библиотеки dll вызывал ошибку связи.

зар
источник
3

Это случилось со мной, поэтому я подумал, что могу поделиться своим решением, настолько простым, насколько оно было:

Проверьте набор символов обоих проектов в Configuration Properties -> General -> Character Set.

Мой проект UnitTest использует по умолчанию Character Set Multi-Byte в то время как мой LIBS , где в Unicode .
Моя функция использовала TCHAR в качестве параметра. В результате в моей библиотеке мой TCHAR был преобразован в WCHAR, но в моем UnitTest это был символ * : символы были разными, потому что в конечном итоге параметры действительно не совпадали .

Enyx
источник
Спасибо, это помогает мне решить проблему :)
Perry Qian-MSFT
1

Я только что обнаружил это LNK2019 происходит во время компиляции в Visual Studio 2015, если я забываю предоставить определение объявленной функции внутри класса.

Ошибка компоновщика была очень загадочной, но я сузил то, чего не хватало, прочитав ошибку, и предоставил определение вне класса, чтобы прояснить это.

Mushy
источник
В некоторых случаях проблема заключается в том, что заголовки, содержащие определения классов, имеют хорошие ссылки / включены, но их соответствующие cpps могут быть недоступны для компоновщика. Лучший способ проверить - просмотреть внешние зависимости проекта в обозревателе решений. Однако VS было бы полезно выдать какое-то предупреждение о существовании / включении файла в отношении ошибки.
Laurie Stearn,
1

в моем случае установите для файла cpp значение «Компилятор C / C ++» в свойстве -> общее разрешение ошибки LNK2019.

pivnothebearrrrrrrrr
источник
0

Для меня работает, если я добавляю эту строку , приведенную ниже в .vcxprojв itemGroupCPP файл, который подключен к заголовочному файлу.

<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) .

user276648
источник