Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Создаем и подключаем DLL

Сейчас мы рассмотрим для чего нужны DLL (Dynamic Link Library - динамически компануемая библиотека) и как их создавать. DLL- это участок кода хранимый в файле с расширением .dll. Код может быть использован другими программами, но сама посебе библиотека прораммой не является. Вобщем-то, динамически компонуемые библиотеки представляют собой набао скомпилированныых функций. Но у ютих библиотек есть свой особенности, так например, если каккието две или более программы для Windows одновременно исполняются и используют функции, находящиеся в одной DLL, то в памяти будет постоянно находится только одна библиотека, обеспечивая тем самым экономное расходование памяти. Загрузка библиотеки в память может быть статической и динамической.

При статической загрузке DLL автоматически загружается при запуске исользующего ее приложения. Такая DLL содержит экспортируемые функции, описание которых находится в файле библиотеки импорта(import library file - .lib). Для использования статической загрузки вы должны на этапе компоновки к программе додключить .lib файл вашей DLL. В C++ Builder это сводится к включения в проект .lib файла через менджер проектов.

При диамической загрузке вы можете загружать DLL при необходимости, выгрузить ее когода она ненужна. Однако работать с такими библиотеками сложнее чем со статическими. Рассмотрим созздание и использование DLL статической загрузки.

Статическая загрузка

Создадим сперва проект (File / New / DLL). Будет создан проект, содержащий следующее:

int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*) {
    return 1;
	}

и длинный коментарий предупреждающий вас о том, что для работо способности вашей DLL необходимо снеи обеспечить поствку некоторых dll если вы используете экземпляры класса String.

Для экспорта и импорта из 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.

Пример DLL: файл P.cpp

//---------------------------------------------------------------------------
#define BUILD_DLL
#include 
#include "p.h"
#pragma hdrstop

//---------------------------------------------------------------------------
// Important note about DLL memory management when your DLL uses the
// static version of the RunTime Library:
//
// If your DLL exports any functions that pass String objects (or structs/
// classes containing nested Strings) as parameter or function results,
// you will need to add the library MEMMGR.LIB to both the DLL project and
// any other projects that use the DLL. You will also need to use MEMMGR.LIB
// if any other projects which use the DLL will be perfomring new or delete
// operations on any non-TObject-derived classes which are exported from the
// DLL. Adding MEMMGR.LIB to your project will change the DLL and its calling
// EXE's to use the BORLNDMM.DLL as their memory manager. In these cases,
// the file BORLNDMM.DLL should be deployed along with your DLL.
// To avoid using BORLNDMM.DLL, pass string information using "char *" or
// ShortString parameters.
//
// If your DLL uses the dynamic version of the RTL, you do not need to
// explicitly add MEMMGR.LIB as this will be done implicitly for you
//-------------------------------------------------------------------------
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*) {
	return 1;
	}

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

void Message(char *s) {
	i=10;
	Application->MessageBox(s,"From DLL",IDOK);
	}

Файл P.h

#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_EXP void Message(char *s);
DLL_EXP int i;

Скомпилируйте проект.

Если вы нажмете 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 можно было использовать необходимо три файла: сама DLL, заголовочный файл и библиотечный файл .lib.

Динамическая загрузка

Динамическая загрузка горазда сложнее. Однако для динамической загрузки требуется только сама 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);- выгрузка библиотеки из памяти.

Обратите внимание на то, что призагрузке можно указать точное местоположние библиотеки (необезательно в том же каталоге где и приложение).

Оставить комментарий

Комментарий:
можно использовать BB-коды
Максимальная длина комментария - 4000 символов.
 

Комментарии

1.
95K
10 мая 2015 года
Мурад Азизов
0 / / 10.05.2015
+6 / -3
Мне нравитсяМне не нравится
10 мая 2015, 21:39:49
Почему столько ошибок в тексте? исправьте!
2.
Аноним
+5 / -0
Мне нравитсяМне не нравится
27 октября 2005, 16:24:48
следует следить что бы совпадали объявление функции в *.dll и *.exe (в частности в этом примере : __stdcall не совпадают, потому выкидывает External exception)
привожу рабочий пример:
void __fastcall TForm1::Button1Click(TObject *Sender) {
void (*Message)(char *s);
HINSTANCE dllp = LoadLibrary("p.dll");
if (dllp) {
Message= (void(*) (char*))
GetProcAddress(dllp, "_Message");
if (Message) Message("Hi From Dinamic DLL");
}
FreeLibrary(dllp);
}
dll-ку оставляем прежнюю
3.
Аноним
+1 / -3
Мне нравитсяМне не нравится
27 октября 2005, 15:00:01
что бы тут не говорили всё предельно ясно и разложено по полочкам как для новичков так и для спецов - интуитивно можно разобраться. Единственно хотелось бы отметить что новоиспечённые самоучки вечно о б с ы р а ю т профанов на всех форумах
4.
Аноним
+0 / -3
Мне нравитсяМне не нравится
12 октября 2005, 10:28:58
Материал изложен некорректно, согласен!
Самому хоть какие-то знания иметь тоже надо, чтобы благодаря им воспользоваться вышеизложенным материалом.
А что касается скрипта, то не надо ля-ля...! Скрипт правильный!
5.
Аноним
+0 / -1
Мне нравитсяМне не нравится
16 августа 2005, 05:17:06
незнаю незнаю.... как вы так делали... у меня все получилось с первого раза (с языком знаком меньше месяца).. а насчет ошибок, вы проверте, там почти везде вместо 1 стоит l (L в нижнем регистре)

мне очень помогло, спасибо авторам!
6.
Аноним
Мне нравитсяМне не нравится
20 июля 2005, 20:45:45
Вот только решил узнать о созданиях dll.
Тут я ничего не понял. Ну по крайней мерее ничего не работает из того что написанно в примере.

7.
Аноним
Мне нравитсяМне не нравится
12 июня 2005, 02:28:16
По поводу предыдущих отзовов:
Народ прежде чем такое писать определитесь доступен ли Ваш уровень подготовки к пониманию вышеизложенного материала. Может быть Вы еще не доросли?

Автору.
Гран мерси. Очень помогло.
8.
Аноним
+1 / -0
Мне нравитсяМне не нравится
9 января 2005, 19:09:22
Автор, миленький, ну нельзя же так путать новичков в мире программирования. Ведь DLL - Статическая загрузка - совершенно разные вещи. DLL - это Dynamic Link Library.
DINAMIC, СЛЫШИШЬ??????!!!!
9.
Аноним
+1 / -0
Мне нравитсяМне не нравится
2 ноября 2004, 22:05:06
Крайне не понятно написанно.По крайне мере сколько я не пробовал сделать то, что было написанно в статье ничего не получилось - постоянно ошибки при чем не знаешь в какую сторону рыть. Так же не понравилось, что автор в статье отказывается от __export и __import. К примеру пересел я на другой комилятор и все разбирай занова.
10.
Аноним
+1 / -1
Мне нравитсяМне не нравится
11 октября 2004, 09:50:59
Неважно изложеный материал, запутанно всё. Знающему человеку может быть все понятно, но ведь это написано для изучающих, незнакомых с этим материалом людей. Плохо что вопросы здесь задавать нельзя, значит и этот материал не будет правлен так, чтобы было логически правильно изложен и навсегда останется таким запутанным.

Судите сами, рассмотрим часть про статическую загрузку,
сначала читаем:
"При статической загрузке DLL автоматически загружается ...Для использования статической загрузки вы должны на этапе компоновки к программе додключить .lib файл вашей DLL. В C++ Builder это сводится к включения в проект .lib файла через менджер проектов."

А потом оказывается этого мало, нужны еще манипуляции:
"добавте в заголовочный файл библиотеки с..."
"в исходном файле DLL напишите..."
"и добавте .lib файл из предыдушего проект с DLL",

Пишется что для статической загрузки исаользуется lib-файл
"(import library file - .lib)" (почему не .ilf?) но для чего-то надо создать проект для DLL, ведь DLL - это библиотека динамической загрузки... Не написано для чего для создания lib нужно создавать проект для dll, ведь lib-библиотеки можно собирать и обычным путем из obj-файлов.

В общем жаль, что такие уроки пишутся без возможности обратной связи и без возможности улучшения мериала, об использовании методики изложения я уже не стану писать.


Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог