При создании DLL в Windows необходимо определить точки входа в библиотеку. Чтобы имена были не декорированные (а именно такие стоит использовать, чтобы не зависеть от компоновщика — он от версии к версии делает совершенно разными) часто используется
DEF-файл. Минимальный DEF-файл выглядит примерно так:
LIBRARY mydll
EXPORTS
CreateSomethingCool @1
Документация MSDN однако умалчивает, что тут мы имеем возможность какие-то функции перенаправлять в другие DLL. Для этого надо написать что-то вроде:
LIBRARY mydll
EXPORTS
CreateSomethingCool @1
WriteConsole=Kernel32.WriteConsoleA
Теперь, если вызвать функцию
WriteConsole из нашей библиотеки, то на самом деле вызовется функция
WriteConsoleA из Kernel32.dll. Такой способ позволяет избежать явных зависимостей от других DLL и создания stub-функций. Указанная DLL будет подгружаться только, если кто-то вызовет конкретную экспортируемую функцию. Такого же результата можно добиться и с помощью директивы pragma:
#pragma comment(linker, "/export:WriteConsole=Kernel32.WriteConsoleA")
В прекрасной утилите Dependency Walker можно посмотреть на результат:
Тут видно, что вместо адреса функции
WriteConsole указано перенаправление на функцию из Kernel32.dll.
Подобным образом можно обращаться и с экспортируемыми данными. Подробнее о том как это можно сделать можно почитать в статье по ссылке ниже.
Ссылки по теме:
- Exported functions that are really forwarders - Raymond Chen
- An In-Depth Look into the Win32 Portable Executable File Format, Part 2 - MSDN
- Forwarding data in a DLL - Stackoverflow.com