Прежде чем мы приступим к реализации динамической загрузки 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