Шаг 92 - Создание DLL, прототипы функций и динамическая линковка

Прежде чем мы приступим к реализации динамической загрузки DLL, полезно рассмотреть возможность использования указателей функций. Для большей наглядности работы с ними как правило используют соответствующее typedef обозначение:

/*
	typedef [return_type] (*[имя_типа]) ([список параметров]);
									*/
typedef void (*func1)(char*);
func1 Message;

Теперь реализация:

//-----dllmain.h----
#define DLL_SPEC extern "C" __export

DLL_SPEC void Message(char *s);

//-----appmain.cpp----
typedef void (*func1)(char*);
func1 Message;

void __fastcall TForm1::Button1Click(TObject *Sender)
{
	if(Message)
		Message("hi!");
	FreeLibrary(lib);
	Message = NULL;
}

//-------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
	HMODULE lib = LoadLibrary("dllproject.dll");
	if(lib)
		Message = (func1)GetProcAddress(lib,"_Message");
}
//----------

Обратите внимание, что при использовании соглашений вызова типа "C", при загрузке функции необходим символ подчеркивания перед именем функции, поскольку линкер в загрузочном модулем все имена снабжает символом подчеркивания. Тем не менее, возможен вариант использования __stdcall обращения:

//-----dllmain.h----
#define DLL_SPEC extern "C" __export

DLL_SPEC void __sdtcall Message(char *s);

//-----appmain.cpp----
typedef void (__stdcall *func1)(char*);
func1 Message;

void __fastcall TForm1::Button1Click(TObject *Sender)
{
	if(Message)
		Message("hi!");
	FreeLibrary(lib);
	Message = NULL;
}

//---------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
	HMODULE lib = LoadLibrary("dllproject.dll");
	if(lib)
		Message = (func1)GetProcAddress(lib,"Message");
}

//----------

В этом случае символ подчеркивания не нужен вовсе.

Помимо имен, данные методы различаются еще и способом передачи параметров. Так что, если после или перед выполнением функции из DLL у вас вылетает Access Violation, а в оригинале все прекрасно работало, то верным признаком этого безобразия является неправильный метод вызова (calling convention).

Если же встали в тупик, много интересной информации можно почерпнуть из своего же DLL с помощью утилиты TDump, используя ее следующим образом:

C:\Projects> tdump  dllexample.dll > dump.txt

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