Неопределенная ссылка на операторы, не являющиеся членами dll

#c #qt #mingw #qt-creator

#c #qt #mingw #qt-creator

Вопрос:

Для присваивания я создал класс фракций, который перегружает много операторов. Затем я преобразовал его в dll для использования другой программой. Проблема, с которой я сталкиваюсь, заключается в том, что когда я пытаюсь использовать операторы, не являющиеся членами, я получаю сообщение об ошибке «неопределенная ссылка на ‘operator ‘».

Я считаю, что я правильно реализовал dll, поскольку конструкторы работают правильно, как и любые функции / операторы-члены. Только операторы, не являющиеся членами, вызывают у меня эту проблему.

         Fraction frac1(1,5); //No errors
        Fraction frac2(2,5); //No errors
        Fraction frac3 = frac2   frac1; //ERROR: undefined reference to 'operator '
        //Note:   operator is a non-member operator
        frac2  = frac1; //No errors and is a member operator
  

Я пытался решить эту проблему и часами искал в Google, но безуспешно. Это может быть проблемой со связыванием, но мне не повезло выяснить это, если это так.

Я использую Qt Creator (поскольку я внедряю графический интерфейс) и MinGW.

Комментарии:

1. Вы добавили __declspec(экспорт) / __declspec(импорт) перед операторами вне класса?

2. У меня нет, я не слышал об этом раньше. Я бы просто сделал frac2 __declspec(импорт) frac1? @MorningDewd

3. Если вы хотите предоставить функции или классы для dll, вы должны «пометить» их спецификацией declspec. То же самое, если вы хотите, чтобы компоновщик знал, что символы, найденные в заголовочном файле, будут получены из .dll. Смотрите Эту ссылку для получения руководства mingw.org/wiki/sampledll

Ответ №1:

Короткая версия: вам необходимо правильно экспортировать / импортировать объекты и код нашей библиотеки.


Длинная версия:

Где-то в вашем заголовке будет определение макроса, подобное следующему:

 #ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(export)
#else
#define MYDLL_API __declspec(import)
#endif
  

Этот макрос позже используется во множестве мест в заголовке и файлах реализации. Например, простая функция объявляется следующим образом:

 MYDLL_API int MyFunction(int);
  

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

 class MYDLL_API MyClass
{
    // members...
};
  

При компиляции вашей DLL (т.Е. Создании фактического проекта DLL) макрос препроцессора, MYDLL_EXPORTS , определяется либо в основном заголовке только для проекта (НЕ в заголовке dll expose’), либо в фактической команде сборки. Это, в свою очередь, делает все MYDLL_API оформленные символы «экспортированными». Т.Е., Используя наш пример API выше, это:

 MYDLL_API int MyFunction(int);
  

становится следующим:

 __declspec(dllexport) int MyFunction(int);
  

При использовании библиотеки импорта заголовка и DLL НЕ определяйте MYDLL_EXPORTS макрос, и, в свою очередь, та же функция decl в заголовке теперь выглядит следующим образом:

 __declspec(dllimport) int MyFunction(int);
  

ОК. Это много информации или что в конечном итоге сводится к этому. У вас есть оператор свободной функции, который объявлен, но не экспортирован в вашей DLL. Т.е. Учитывая все вышесказанное, у вас есть класс Fraction , который, вероятно, выглядит следующим образом:

 class MYDLL_API Fraction
{
    // members
};
  

а также оператор свободной функции, который выглядит следующим образом:

 Fraction operator  (Fraction, Fraction);
  

Последнее должно выглядеть следующим образом:

 MYDLL_API Fraction operator  (Fraction, Fraction)