На самом деле вам нужен только файл .dll.Он содержит весь необходимый код и данные для запуска своих функций.Он также содержит таблицу, которая связывает символические имена функций (например, функцию PrintMe), их порядковые номера (номер этой функции в DLL) и их адреса в DLL.
Если вы хотите использовать только DLL, вы должны «вручную» получить разрешенные символы:
Допустим, вы хотите использовать функцию PrintMe библиотеки DLL.Вам нужно было разрешить его имя (PrintMe) или его порядковый номер (PrintMe - первая функция DLL) в его адрес.Для этого вы можете использовать LoadLibrary, GetModuleHandle и GetProcAdress из Win32 API (он же Windows SDK).Кроме того, этот метод позволяет загружать DLL во время выполнения (см. Ниже).
Более простой способ - использовать функции MSVC (++) __declspec (dllexport) и __declspec (dllimport), например,
// your DLL
__declspec(dllexport) void PrintMe()
{
printf("Hello World!");
}
// you project to use the DLL
__declspec(dllimport) void PrintMe();
Первый (dllexport) сообщает компилятору экспортировать функцию.Второй (dllimport) является интересным: он создает весь необходимый код, чтобы иметь возможность использовать функцию из DLL.
Для этого вам нужен файл .lib в вашем проекте (который хочет использовать DLL)..Lib-файл содержит информацию для компоновщика, чтобы разрешить имя символа (PrintMe) по его адресу в DLL.Поскольку .lib статически связан, компоновщик может использовать его - DLL, напротив, привязан во время выполнения / загрузки, поэтому компоновщик не может его использовать.(Да, информация в файле .lib избыточна.)Примечание: Вы не можете изменить всю DLL при использовании этого метода без перестройки проекта с новым файлом .lib.Некоторые структурные изменения влияют на адреса функций в DLL, см. этот ответ SO .
Последнее различие между использованием Win32 API (LoadLibrary ...) и метода MSVC через __declspec - загрузкаиз DLL.Когда вы используете LoadLibrary, DLL, разумеется, загружается во время выполнения (так что вы можете перехватывать исключения, когда они не могут быть найдены и т. Д.).Другой метод загружает DLL во время загрузки, поэтому ваша программа будет прервана (не будет запущена), когда Windows не сможет найти DLL.
Когда вы создаете проект в VS, вы можете активировать флажок «экспортировать символы»в конце мастера (проект Win32).Это дает вам несколько примеров экспортируемых символов.Кроме того, он вводит макрос, плюс определение препроцессора, а также некоторые очень полезные директивы:
// DLL header
#ifdef _YOUR_DLL_EXPORTS
#define YOUR_DLL_API __declspec(dllexport)
#else
#define YOUR_DLL_API __declspec(dllimport)
#endif
YOUR_DLL_API PrintMe();
Теперь вы можете использовать этот заголовочный файл для построения вашей DLL, так как ваш проект DLL имеет это определение _YOUR_DLL_EXPORTS (см. Свойства проектастраница, C ++, препроцессор).Проект, который использует DLL, также может использовать этот заголовок, но тогда не должно быть задано такое имя.Когда вы включаете файл заголовка в проект, в котором вы хотите использовать DLL, макрос разрешается в __declspec (dllimport).Это инструктирует компоновщик искать эту функцию (которая находится в .lib-файле) и создает весь необходимый код для загрузки DLL во время выполнения и разрешения имени символа.