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