Шаг 41 - Явный вызов функций DLL

Явный вызов функций DLL несколько утомителен, зато дает Вашей программе настоящий полный контроль за работой DLL. Вы можете спокойно определить есть ли DLL и вообще есть ли в ней соответствующая функция. Давайте посмотрим как это делается. Сначала нам надо получить указатель на DLL - это делает функция LoadLibrary():

HMODULE LoadLibrary
( 
	LPCTSTR lpLibFileName	// имя модуля
);

Она может завершиться как успешно, так и нет. Если успешно, то вернет указатель на DLL. Что она сделает ? Она поищет DLL. Еcли найдет, то загрузит ее в память и вернет Вам указатель. Так как DLL загружается в память Вы не можете просто так ее бросить, Вам надо ее выгрузить, а для этого есть функция FreeLibrary(), которая как раз сообщит Windows, что данная программа DLL больше не использует. Вообще за загрузку и выгрузку DLL отвечает Windows, так как DLL может использоваться несколькими программами. Вы просто говорите, что программа начинает использовать DLL (LoadLibrary) и заканчивает (FreeLibrary), а OC сама разбирается надо грузить ее в память или наоборот убирать, так как никто не использует ее. Вот пример:

// TestDLL.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "windows.h"
#include "iostream.h"

void main()
{
	HINSTANCE hModule=NULL;
	hModule=::LoadLibrary("user32.dll");
	if (hModule!=NULL)
	{
		::FreeLibrary(hModule); 
	}
	else cout << "error load Dll" << endl;
}

Как только мы получили указатель на DLL мы можем получить адрес функции по имени функции. Естественно нам имя нужно знать. Сначала надо объявить прототип функции typedef BOOL (WINAPI MESS)(UINT);. Обратите внимание, что я явно указал тип вызова WINAPI, что означает _stdcall так как С++ использует _cdecl, который не совместим с WIN32 API. Объявив прототип я могу создать указатель на функцию, а потом воспользовавшись GetProcAddress() получить функцию и уже ее вызывать.

// TestDLL.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "windows.h"
#include "iostream.h"

void main()
{
	HINSTANCE hModule=NULL;
	typedef  BOOL (WINAPI MESS)(UINT);
	MESS* me=NULL;
	hModule=::LoadLibrary("user32.dll");
	if (hModule!=NULL)
	{
		me=(MESS*)::GetProcAddress((HMODULE)hModule,"MessageBeep");
		if (me!=NULL)
		{
			UINT type=1;
			BOOL result;
			result=(*me)(type);
		}
		else cout << "Error Load function" << endl;
		::FreeLibrary(hModule); 
	}
	else cout << "error load Dll" << endl;

Внимание !!! Тщательно следите на типом вызова функций. Win32 пользуется методом вызова функций PASCAL - _stdcall, а VC методом вызова C, а в Windows стандарт вызова функций PASCAL. Разница этих методов в помещении параметров в стек. Будет время напишу подробнее. Просто помните об этом. Свои DLL Вы можете вызывать без WINAPI, а вот чужие надо знать, если стандартный API, то WINAPI, иначе надо выяснять. Как ?? Просто получаете ошибку вызова, если ошибетесь :-)

41.gif (3900 b)


Предыдущий Шаг | Следующий Шаг | Оглавление
Автор Каев Артем - 8.01.2001