Явне завантаження DLL у Visual Studio

1. Проблема

Не викликаються функції з DLL при явному завантаженні. При неявному завантаженні функції викликаються успішно.

2. Причина

Долслідження показало, що функція LoadLibrary() спрацьовує успішно, але наступна функція GetProcAddress() призводить до краху програми. Очевидно, GetProcAddress() не може знайти потрібну функцію всередині динамічної бібліотеки. Як бути?
Відкриваємо утиліту командного рядка Visual Studio (Средства > Командная строка Visual Studio). Переходимо в каталог з динамічною бібліотекою (cd D:\Projects\mydll\Debug). Запускаємо утиліту dumpbin.exe з ключем /exports (dumpbin /exports mydll.dll).
І що ми бачимо?

1    0 00011118 ?MyDLLFunction_Load@@YAXPAX@Z

DLL містить функцію ?MyDLLFunction_Load@@YAXPAX@Z замість очікуваної функції MyDLLFunction_Load

Справа в тому, що компілятор C++ застосовує декорацію (mangling) імен функцій, в результаті після компіляції функція має іншу сигнатуру. Декорація імен потрібна для підтримки механізму перевантаження функцій - функції з однаковими іменами, але різними наборами параметрів повинні мати різні сигнатури. Кожний компілятор по-своєму декорує імена функцій.

3. Вирішення проблеми

Можна підставити у функцію GetProcAddress() задекороване ім'я і це спрацює, але це не найкращий шлях. DLL можуть бути створені за допомогою різних компіляторів і викликатися з програм, написаних різними мовами. Ім'я функції повинно бути таким, яким ми його оголосили при створенні DLL. Отже, потрібно заборонити декорування імен.

Для цього використовують модифікатор extern "C", який забезпечує експорт функцій з DLL в стилі мови C

#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif
extern "C" MYDLL_API void MyDLLFunction_Load(HANDLE hOut);

У цьому випадку функція додається в DLL без декорації. Перевіряємо за допомогою dumpbin, функція в DLL має потрібну нам назву MyDLLFunction_Load

1    0 000110D2 MyDLLFunction_Load = @ILT+205(_MyDLLFunction_Load)

Створення і використання DLL у Visual Studio покроково описано в Довідці Microsoft C++.