Чтобы было ясно:
Мне известно, что приведенный ниже пример демонстрирует dll-зависимость, то есть одна библиотека не является самостоятельной, а зависит от другой библиотеки.
Допустим, я создаю библиотеку времени выполнения Utility.dll, которая содержит различные полезные функции общего характера.
Я создаю заголовочный файл Utility.h для включения в другие файлы, которые должны использовать Utility.dll.
Заголовочный файл выглядит так
#ifndef _UTILITY_H
#define _UTILITY_H
#ifdef BUILD_DLL
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif
DLL_EXPORT void foo();
DLL_EXPORT void foo2();
....
#endif
Когда я компилирую файл исходного кода Utility.cpp в машинный код (в Utility.dll), я проверяю, определен ли BUILD_DLL, поэтому DLL_EXPORT заменяется на __declspec (dllexport). Это позволяет экспортировать функции в файл .dll.
Всякий раз, когда я включаю заголовок Utility.h и связываюсь с библиотекой импорта (Utility.lib для MS VS, libUtility.a для g ++) и делаю не определить BUILD_DLL, объявления функций в Utility.h вместо этого начинаются с __declspec (dllimport), сообщая компилятору, что функции импортируются из .dll (так сказать).
Теперь, допустим, я тоже строю другой библиотека MyLibrary.dll, которая хочет использовать некоторые полезные функции в Utility.dll. Точно так же я бы создал MyLibrary.h как
#ifndef _MYLIBRARY_H
#define _MYLIBRARY_H
#ifdef BUILD_DLL
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif
DLL_EXPORT void myLibraryFunc1();
....
#endif
Когда я компилирую MyLibrary.cpp в MyLibrary.dll, я включаю Utility.h, а также связываюсь с библиотекой импорта Utility.
Это приводит нас к моей вопрос:
Поскольку я определяю BUILD_DLL также при компиляции MyLibrary.dll, это означает, что объявления функций в Utility.h также будут читать
__declspec(dllexport) void foo();
__declspec(dllexport) void foo2();
....
Не
__declspec(dllimport) void foo();
__declspec(dllimport) void foo2();
Разве мы не хотим, чтобы это было __declspec (dllimport) для объявлений функций в Utility.h, когда мы компилируем MyLibrary.dll, и __declspec (dllexport) для объявлений функций в MyLibrary.h?
Именно поэтому вы обычно не называете такие макросы BUILD_DLL
, но BUILD_UTILITY
а также BUILD_MYLIBRARY
или похожие. Аналогично, макрос declspec не должен быть DLL_EXPORT
, но UTILITY_EXPORT
а также MYLIBRARY_EXPORT
(или возможно UTILITY_API
а также MYLIBRARY_API
).