Я столкнулся с некоторым поведением, которое, насколько я понимаю, должно вызвать ошибку компоновщика.
У меня есть два проекта C ++ MyLib и MyLibTests . MyLib - это проект windows dll. В этом проекте есть заголовочный файл Declspe c .h
// Declspec.h
#pragma once
#define NATIVE_API __declspec(dllexport)
#define NATIVE_API_CALL __cdecl
, который используется для аннотирования функций, которые должны быть экспортированы (для их проверки).
Теперь есть несколько заголовочных файлов, которые объявляют функции, например GUID.h (я вырезал ненужные части):
// GUID.h
NATIVE_API GUID newGuid();
и связанные с ними исходные файлы, например GUID. cpp:
// GUID.cpp
GUID newGuid()
{
GUID g;
(void)CoCreateGuid(&g);
return g;
}
MyLib builds GUID. cpp и пока все в порядке. Теперь MyLibTests ссылается на dll и вызывает функцию newGuid()
. Для этого тот же GUID.h включен в MyLibTests . Код компилируется, и похоже, что он работает правильно. Это точка, которую я не понимаю. Включая GUID.h , мы транзитивно включаем Declspe c .h , который разрешает макрос NATIVE_API
в __declspec(dllexport)
, что означает, что функция должна быть снова экспортирована (что само по себе уже неправильно). Я предположил, что dllexport
требует, чтобы определение было доступно в одной из единиц перевода (а именно GUID. cpp здесь), чтобы разрешить экспорт. Но поскольку GUID. cpp является , а не , созданным как часть проекта MyLibTests , я ожидаю ошибку компоновщика вместо успешной сборки.
Насколько я знаю, Declspe c .h выглядит следующим образом:
// Declspec.h
#ifdef SOME_PROJECT_DEPENDEND_MACRO
# define NATIVE_API __declspec(dllexport)
#else
# define NATIVE_API __declspec(dllimport)
#endif
и SOME_PROJECT_DEPENDEND_MACRO
, являющиеся макросом, объявленным в файле проекта проект, который обеспечивает функцию. Таким образом, все включенные в определяющий проект получают подпись dllexport
, в то время как все ссылающиеся проекты включают заголовочные файлы с подписью dllimport
(и, следовательно, не ищут определения внутри своих собственных модулей перевода).
Почему оба проекта успешно компилируются (и выполняются), несмотря на то, что все функции всегда dllexport
ed в обоих проектах?