Системное программирование в среде Windows
Шрифт:
Имя файла, связанного с дескриптором hHandle, можно получить с помощью функции GetModuleFileName. Возможно и обратное: для заданного имени файла (.DLL или .EXE) функция GetModuleHandle в случае успешного выполнения возвратит дескриптор, связанный с этим файлом, если текущий процесс загрузил его.
В следующем примере показано, как использовать адрес точки входа для вызова функции.
Пример: явное связывание функци и преобразования файлов
Программа 2.4, предназначенная для преобразования кодировки текстовых файлов
Программа 5.7 является модифицированным вариантом вызывающей программы, обеспечивающим возможность принятия решения относительно того, какой вариант реализации функции преобразования должен быть загружен, во время выполнения. Программа загружает DLL, получает адрес точки входа Asc2Un и вызывает функцию. В данном случае существует только одна точка входа, но реализовать вариант с несколькими точками входа не составляет особого труда. Основная программа является, по существу, той же, что и прежде, за исключением того, что библиотека DLL, которую необходимо использовать, указывается в виде параметра командной строки. В упражнении 5.9 вам предлагается написать вариант программы, в котором нужная DLL определяется на основе свойств системы и файла. Обратите внимание на то, каким образом осуществляется приведение типа адреса FARPROC к типу соответствующей функции с использованием необходимого в этом случае, но довольно сложного, синтаксиса С.
Создание библиотек DLL на основе функции Asc2Un
Программа тестировалась с двумя функциями преобразования файлов, которые должны были создаваться в виде библиотек DLL, имеющих различные имена, но идентичные точки входа. В данном случае существует только одна точка входа. Единственным существенным изменением в исходном коде является добавление модификатора _declspec(dllexport) для экспортирования функции.
Точки входа библиотеки DLL
Для каждой создаваемой DLL вы можете указать точку входа запуска библиотеки, которая обычно автоматически вызывается при каждом подключении или отключении процесса. В то же время, в функции LoadLibraryEx предусмотрена опция, позволяющая подавить вызов точки входа. В случае неявно связываемых (связываемых во время выполнения) библиотек DLL подключение и отключение процесса происходит, соответственно, при его запуске и завершении. В случае же явно связываемых DLL это осуществляется при вызове функций LoadLibrary, LoadLibraryEx и FreeLibrary.
Кроме того, точка входа вызывается всякий раз, когда процесс создает новый поток (глава 7) или прекращает его выполнение.
Точкой входа с именем DllMain, прототип которой приводится ниже, мы воспользуемся в полной мере только в главе 12 (программа 12.4), где она предоставит потокам удобный способ управления ресурсами и так называемыми локальными областями хранения потоков (Thread Local Storage, SLT) в DLL с многопоточной поддержкой.
Параметр hDll является дескриптором экземпляра DLL, возвращенным функцией LoadLibrary. Значение NULL параметра Reserved указывает на то, что подключение процесса к библиотеке произошло в результате вызова функции Load-Library; иные значения этого параметра свидетельствуют о подключении к библиотеке в результате неявного связывания во время загрузки. Подобным образом, к значению NULL параметра Reserved приводит и отключение процесса от библиотеки в результате вызова функции FreeLibrary.
Параметр Reason может иметь одно из четырех значений: DLL_PROCESS_ATTACH, DLL_THREAD_ATTACH, DLL_THREAD_DETACH и DLL_PROCESS_DETACH. Функции точки входа DLL обычно используют операторы switch и в качестве индикатора успешного выполнения возвращают значение TRUE.