Урок 37 Создание DLL.
April 15, 2007
в колонках играет Pink Floyd - Dogs
В этом уроке мы рассмотрим для чего нужны DLL (Dynamic Link Library - динамически компануемая библиотека) и как их создавать. DLL- это код, который хранится в файле * .dll. Сама по себе библиотека прораммой не является. У этих библиотек есть свои особенности, например если каккие-то две или более программы для Windows одновременно исполняются и используют функции, находящиеся в одной DLL, то в памяти будет постоянно находится только одна библиотека, обеспечивая экономное расходование памяти. Загрузка библиотеки в память может быть статической и динамической. При статической загрузке DLL автоматически загружается при запуске исользующего ее приложения. Такая DLL содержит экспортируемые функции, описание которых находится в файле библиотеки импорта(import library file - .lib). Для использования статической загрузки вы должны на этапе компоновки к программе додключить .lib файл вашей DLL. В C++ Builder это сводится к включения в проект .lib файла через менджер проектов. При диамической загрузке вы можете загружать DLL при необходимости, выгрузить ее когода она ненужна. Однако работать с такими библиотеками сложнее чем со статическими.
Статическая загрузка
Создадим сперва проект (File / New / DLL). Будет создан проект, содержащий следующее:
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*)
{
return 1;
}
Для экспорта и импорта из DLL необходимо использовать моди фикаторы __export и __import соответсвенно. Но в C++ Builder можно использовать новое ключевое слово __delspec() с параметрами dllexport и dllimport соответсвенно. Для того чтобы эспортировать функции из библиотеки нужен заголовочный файл с описаниями _delspec(dllexport) для экспортируемых функций, для импорта функций в приложение необходимо будет поставить анологичный заголовочный файл но с _delspec(dllimport) описаниями, что достаточно неудобно. Эта проблема решается легко: добавте в заголовочный файл библиотеки следующее:
#if defined(BUILD_DLL)
# define DLL_EXP __declspec(dllexport)
#else
# if defined(BUILD_APP)
# define DLL_EXP __declspec(dllimport)
# else
# define DLL_EXP
# endif
#endif
в исходном файле DLL напишите #define BUILD_DLL, а вместо __declspec(dllexport) пишите DLL_EXP.
При написании программы добавте строчку #define BUILD_APP, и просто подключите заголовочный файл DLL.
Если вы нажмете Run то после завершенния построения будет выдано
сообщение что данная программа не можнт быть исполнена.
Теперь напишем вызывающую программу.
В том же каталоге создайде новый проект
(File / New Application) в форму поместите одну кнопку и создайте обработчик события OnClick.
Файл должен быть таким:
//----------------------------------------------------
#include
#define BUILD_APP
#pragma hdrstop
#include "p.h"
#include "Unit1.h"
#include
//-----------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) {
}
//-------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender) {
char c[10];
Message("roma");
for( ; i>0;i--) {
sprintf(c,"Example %d",i );
Application->MessageBox("Example of using DLL variable",(char*)c,IDOK);
}
}
//---------------------------------------------------------
Не забудьте об объявлениях в начале файла. Зайдите в менеджер проектов.
Там откройте свой проект и добавте .lib файл из предыдушего проект с DLL( правый клик, пункт ADD).
Запускайте!
Динамическая загрузка горазда сложнее. Однако для динамической загрузки
требуется только сама DLL ( не ненужен ни .lib ни заголовочный файл, хотя
его можно исполбзовать для описания экспортируемых функций для предполагемого пользователя).
Давайте рассмотрим на примере, как производится динамическая загрузка. Создайте новый прокт
DLL и внесите в него следующее:
extern "C" void __export Message(char *s)
{
Application->MessageBox(s,"From DLL",IDOK);
}
Cкомпилируйте проект, в результате чего будет создана DLL.
Теперь создайте проект приложения анологичный проекту для использования статической загрузки
(форма с кнопкой и обработчиком события кнопки OnClick) ниже приведен код приложения:(Unit11.cpp)
//--------------------------------------------
#include
#pragma hdrstop
#include "Unit11.h"
#include
//---------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//----------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
{
}
//----------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
void (__stdcall *Message)(char *s);
HINSTANCE dllp = LoadLibrary("p.dll");
if (dllp) {
Message= (void(__stdcall *) (char*))
GetProcAddress(dllp, "_Message");
if (Message) Message("Hi From Dinamic DLL");
}
FreeLibrary(dllp);
}
//----------------------------------------------
запустите это проект, при нажатии на кнопку должно выдаватся сообшение.
void (__stdcall *Message)(char *s);-объявление указателя на функцию.
HINSTANCE dllp = LoadLibrary("p.dll");- загрузка библиотеки в память.
Message= (void(__stdcall *) (char*)) GetProcAddress(dllp, "_Message");присвоение указателю адреса функции DLL.
Message("Hi From Dinamic DLL"); рабочий вызов фунциий (собственно то для чего все это и делается).
FreeLibrary(dllp);- выгрузка библиотеки из памяти.
Author of article - [ArtuR] 2007
www.builderhelper.3dn.ru
builder.helper@rambler.ru