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