Создание и использование DLL
(Microsoft Visual C++)
Введение
Создать DLL намного легче, чем вы думаете. Библиотеки DLL очень полезны, если
вы программируете под Windows. В этих библиотеках обычно хранят часто используемые
подпрограммы. В статье рассказывается как создать простую DLL и показано, как
вызвать функции, содержащиеся в ней. Примеры расчитаны на использование Microsoft
Visual C++ 6.0, но нетрудно перевести их на любой диалект C++.
Создание DLL
Ничего особенного здесь нет. Как обычно, вы просто пишите функции, как в обычной
программе. Если вы используете MSVC, создайте новый проект и укажите, что вы
создаете Win32 Dynamic-Link Library. После компиляции вы получите DLL, библиотеку
импорта (.lib) и библиотеку экспорта (.exp). Далее показан примерный код вашей
DLL:
Заголовочный файл (DLLTEST.H)
#ifndef _DLLTEST_H_
#define _DLLTEST_H_
#include <iostream.h>
#include <stdio.h>
#include <windows.h>
extern "C" __declspec(dllexport) void NumberList();
extern "C" __declspec(dllexport) void LetterList();
#endif
|
Код библиотеки (DLLTEST.CPP)
#include "dlltest.h"
#define MAXMODULE 50
char module[MAXMODULE];
extern "C" __declspec(dllexport) void NumberList()
{
GetModuleFileName(NULL, (LPTSTR)module, MAXMODULE);
cout << "nnThis function was called from
"
<< module
<< endl << endl;
cout << "NumberList(): ";
for(int i=0; i<10; i++)
{
cout << i << " ";
}
cout << endl << endl;
}
extern "C" __declspec(dllexport) void LetterList()
{
GetModuleFileName(NULL, (LPTSTR)module, MAXMODULE);
cout << "nnThis function was called from
"
<< module
<< endl << endl;
cout << "LetterList(): ";
for(int i=0; i<26; i++)
{
cout << char(97 + i) <<
" ";
}
cout << endl << endl;
}
|
Как видите, ничего особенного в коде нет. Приложение, используемое для примера
- консольное, так что здесь просто запрограммированы две функции, выводящие
текст. Строка
extern "C" __declspec(dllexport)
означает, что функция будет видна вне DLL (т.е. ее можно вызывать из нашей программы).
После компиляции мы получим библиотеку. Теперь посммотрим, как ее можно использовать.
Использование DLL (с библиотекой импорта)
Сначала посмотрим, как использовать DLL вместе с библиотекой импорта (dlltest.lib),
которая получается при компиляции предыдущего примера. Этот метод очень прост,
так как в таком случае нужно просто включить заголовочный файл библиотеки и
саму библиотеку в проект. Пример:
Исходный файл приложения, использующего библиотеку DLL (DLLRUN01.EXE)
#include <conio.h>
#include <dlltest.h>
void main()
{
NumberList();
LetterList();
getch();
}
|
Это будет прекрасно работать, если у вас есть заголовочный файл и библиотека
импорта (dlltest.lib) находится в каталоге, прописанном в библиотечных путях.
Перед запуском приложения, убедитесь, что DLL находится в каталоге, прописанном
в системной переменной PATH или в том же каталоге, что и исполняемый файл, иначе
вы получите сообщение об ошибке. Однако если 10 программ используют эту DLL,
вам нужна всего одна ее копия, лежащая, например, в каталоге WindowsSystem.
Результаты работы DLLRUN01.EXE
This function was called from C:DLLTESTDLLRUN01.EXE
NumberList(): 0 1 2 3 4 5 6 7 8 9
This function was called from C:DLLTESTDLLRUN01.EXE
LetterList(): a b c d e f g h i j k l m n o p q r s t u v w x y z
|
Использование DLL без библиотеки импорта
Теперь посмотрим, как загрузить DLL "на лету". Это нужно в случае,
если не вы разрабатывали эту DLL и у вас нет заголовочного файла и библиотеки
импорта.
Исходный файл приложения, использующего библиотеку DLL - консольное приложение
Win32 (DLLRUN01.EXE)
#include <windows.h>
#include <iostream.h>
#include <stdio.h>
#include <conio.h>
#define MAXMODULE 50
typedef void (WINAPI*cfunc)();
cfunc NumberList;
cfunc LetterList;
void main()
{
HINSTANCE hLib=LoadLibrary("DLLTEST.DLL");
if(hLib==NULL)
{
cout << "Unable to load
library!" << endl;
getch();
return;
}
char mod[MAXMODULE];
GetModuleFileName((HMODULE)hLib, (LPTSTR)mod, MAXMODULE);
cout << "Library loaded: " <<
mod << endl;
NumberList=(cfunc)GetProcAddress((HMODULE)hLib, "NumberList");
LetterList=(cfunc)GetProcAddress((HMODULE)hLib, "LetterList");
if((NumberList==NULL) || (LetterList==NULL))
{
cout << "Unable to load
function(s)." << endl;
FreeLibrary((HMODULE)hLib);
return;
}
NumberList();
LetterList();
FreeLibrary((HMODULE)hLib);
getch();
}
|
Этот код загружает DLL (если она находится в путях или в текущем каталоге),
а затем определяет адреса функций, которые мы будем вызывать. Конечно, в этом
случае пришлось написать намного больше кода, и, соответственно, придется отловить
немало ошибок. Однако такой подход универсальней.
Результаты работы DLLRUN02.EXE
Library loaded: C:DLLTESTDLLTEST.DLL
This function was called from C:DLLTESTDLLRUN02.EXE
NumberList(): 0 1 2 3 4 5 6 7 8 9
This function was called from C:DLLTESTDLLRUN02.EXE
LetterList(): a b c d e f g h i j k l m n o p q r s t u v w x y z
|
Заключение
Конечно, эти небольшие примеры далеки от реальных задач программиста, однако
они вполне достаточны, чтобы понять основные принципы создания и использования
DLL. Напишите, если вы нашли ошибки или неточности. Скачать исходные тексты
программ, используемых в статье, можно отсюда
.
|