Создание 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
 
« Предыдущая статья   Следующая статья »