psilogic: (Default)
[personal profile] psilogic
Возникает ошибка линковки:
error LNK2005: public: __thiscall ArrayHolder<char>::ArrayHolder<char>(void)" (??0?$ArrayHolder@D@@QAE@XZ) already defined in excel.obj

Причины я знаю (ниже), вопрос в том, как их культурно лечить.

1. Есть DLL и прога, которая ее юзает (то же самое, когда другая DLL, юзает первую DLL).

2. В одном из хэдеров DLL (arrayholder.h) определен некий темплейтный класс:

template <class T>
class ArrayHolder<T>
{
public:
ArrayHolder() {}
...
};

3. В одном из хэдеров DLL (someclass.h) определен некий класс, унаследованный от ArrayHolder<char> - не напрямую а через цепочку, но это неважно:

class EXPORTIMPORT SomeClass: public ArrayHolder<char>
{
...
};

У этого класса в someclass.cpp определена куча функций, которые используются как в DLL, так и в проге.

4. В проге, в некоем модуле excel.cpp создается и используется объект типа ArrayHolder<char>.

Проблема, похоже, в следующем.

Когда компилируется DLL, компилятор создает код конструктора ArrayHolder::ArrayHolder() внутри DLL, и его код экспортируется наружу вместе с конструктором SomeClass,

Когда компилируется excel.cpp, компилятор не знает о том, что ArrayHolder::ArrayHolder() уже есть в DLL-ке, и создает его еще раз. Ошибка обнаруживается на этапе линковки.

Мне известно одно лекарство: надо сделать #include <someclass.h> в модуле excel.cpp. Тогда компилятор будет знать об этом экспорте уже на этапе компиляции.

Но это плохой путь, поскольку класс SomeClass реально не используется в модуле excel.cpp. Неочевидно, что, всякий раз, когда используешь ArrayHolder<char> надо добавить не только хэдер ArrayHolder, но и хэдеры всех классов в DLL, которые используют ArrayHolder<char>.

Upd: Как проблема решилась.


Вариант 1:
В конец arrayholder.h добавить:
class IMPORTEXPORT ArrayHolder_char_dummy: public ArrayHolder<char>
{
};
- в результате компилятор всегда будет знать, что эта специализация есть в DLL-ке.

Вариант 2:
(только для Microsoft Studio)
В конец arrayholder.h добавить:
#if EXPORT
template class IMPORTEXPORT ArrayHolder<char>;
#else
extern template class IMPORTEXPORT ArrayHolder<char>;
#endif
- результат тот же, правда, сыпятся warning-и, что 'nonstandard extension used'...

(deleted comment)

Date: 2008-05-22 08:17 pm (UTC)
From: [identity profile] psilogic.livejournal.com
Нашел решение и еще одно на ru_cpp подсказали. Написал upd.

Date: 2008-05-23 05:53 pm (UTC)
From: [identity profile] ex-ketmar.livejournal.com
хорошо, ой, как хорошо-то!
(ц) онегдод про доктора и больного

Date: 2008-05-23 06:39 pm (UTC)
From: [identity profile] psilogic.livejournal.com
не помню такого анегЫдота, колись? :)

Date: 2008-05-23 06:44 pm (UTC)
From: [identity profile] ex-ketmar.livejournal.com
пациент на обследовании:
— ну и как там у меня, доктор?
— хорошо, ай, как хорошо, просто отлично!
— что хорошо-то, доктор?
— хорошо, что у меня такого нет!

Date: 2008-05-23 06:54 pm (UTC)
From: [identity profile] ex-ketmar.livejournal.com
а всё от того, что нехуй пихать классы в DLL духовности и благодати нет.
(deleted comment)

Date: 2008-05-28 01:56 pm (UTC)
From: [identity profile] ex-ketmar.livejournal.com
>Тот же ATL
а хрен его знает. я никогда не был настолько помрачён сознанием, чтобы писать на цпп цто-либо сложнее софтины «fuck stroustrup!» какая, в общем-то, разница, как там реализовали очередной костыль…

Date: 2008-05-28 02:00 pm (UTC)
Page generated Aug. 12th, 2025 11:50 pm
Powered by Dreamwidth Studios