Рассмотрим класс, который относится к проекту, связанному с динамической библиотекой (foo.dll), с foo.lib, сгенерированным также на стороне:
class IMP_EXP_DIRECTIVE_MACRO Foo
{
void bar()
{
// do something
}
};
Затем есть еще одна панель проекта (генерирующая статический файл).библиотека bar.lib), которая включает этот класс.Проект не связывается с foo.
Наконец, есть проект приложения (в результате .exe), который связывается как с foo.lib, так и с bar.lib.Когда это происходит, компоновщик выдает ошибку LNK2005 о том, что Foo::bar
уже определен как в файле foo.lib (что хорошо), так и в файле bar.lib, что является неожиданным и странным.
При обработке bar.lib с помощьюdumpbin.exe / SYMBOLS согласно выводу https://docs.microsoft.com/en-us/cpp/build/reference/symbols?view=vs-2017 показывает, что Foo::bar
действительно определен в foo.lib (!).Это странно, поскольку согласно этому блестящему ответу https://stackoverflow.com/a/4955288 любая функция-член, объявленная и определенная в теле класса, неявно встроена, поэтому не вызывает проблем с ODR.
Наконец,самая интересная часть.При перемещении определения Foo::bar
в файл .cpp и оставлении только объявления метода в теле класса проблема исчезает.
Почему это так?Есть идеи, что делается неправильно?Я думаю, что прочитал весь Интернет на эту тему и перепробовал все различные параметры конфигурации VS, но помогает только перемещение определения в .cpp.В принципе, я могу в конечном итоге сделать это, но это не кажется правильным решением проблемы.
Среда: Visual Studio 10.
edit:
IMP_EXP_DIRECTIVE_MACRO имеет значение:
"__declspec (dllexport)", при сборке foo.dll
"", при сборке bar
edit 2:
Problemтакже пропал, когда в компилятор bar.lib добавлен флаг препроцессора, который вызывает использование class __declspec(dllimport) Foo
вместо class Foo
.
Это правильный путь?