В прошлый раз мы видели как экспортируемые функции в Win32 ведут себя похоже на экспорт функций в 16-битных Windows - только сместился акцент использования с импорта по номеру на импорт по имени. Этот акцент никак не выражен в формате исполняемого файла; и 16-битные и 32-битные DLL могут экспортировать функции по номеру и имени (и обоим одновременно).
Но в Win32 появляется новый тип экспортируемых функций, известный как forwarder.
Forwarder выглядит как обычная экспортируемая функция, за исключением того что запись в таблице экспорта по номерам говорит "Ох, на самом деле, я не функция в этой DLL. На самом деле - я функция вон в той DLL". К примеру, если вы сделаете
link /dump /exports kernel32.dllТо вы увидите что-то такое:
151 EnterCriticalSection (forwarded to NTDLL.RtlEnterCriticalSection)
Это означает, что если программа связана с
KERNEL32.EnterCriticalSection
, то загрузчик ОС молчаливо перенаправит функцию на NTDLL.RtlEnterCriticalSection
. Forwarder-ы являются удобным способом сохранить внешний интерфейс, изменив функциональность выносом в отдельные DLL. Старая DLL продолжает экспортировать функцию, но сама функция была перемещена в новую DLL.Трюк с forwarder - это лучше, чем иметь пустую функцию-заглушку в старой DLL, которая просто вызывает функцию в новой DLL: потому что функция заглушка создаёт зависимость между новой и старой DLL (в конце концов, старую DLL нужно связать с новой DLL, чтобы была возможность вызвать функцию!). А при использовании forwarder новая DLL не будет загружаться, если только кто-то не попросит перенаправленную функцию из старой DLL. В результате вы не платите за загрузку новой DLL пока кто-то её явно не попросит.
Okей, как мы увидели, с введением forwarder Win32 отошла от 16-битных Windows, но как только мы посмотрим на импорт, то увидим, что тут изменилось вообще всё. Мы посмотрим на эту историю в следующий раз.
Эх, еще бы знать, как в Delphi сделать именно такую функцию в DLL...
ОтветитьУдалить> Эх, еще бы знать, как в Delphi сделать именно такую функцию в DLL
ОтветитьУдалитьЭлементарно. Как я когда-то делал враппер. В interface описываете функцию как экспортируемую, а в implementation - как импортируемую. :)