Й вариант. Работа с методами класса без использования их номеров
Для реализации этого варианта потребуется выполнить ряд дополнительных действий:
а) в динамически подключаемой библиотеке:
- описать дополнительно две функции для создания и уничтожения динамического объекта класса в DLL;
- все открытые методы в классе необходимо объявить виртуальными.
б) в приложении, которое явно загрузит эту DLL:
- получить адреса функций, которые создают и уничтожают объект класса в DLL с помощью функции GetProcAddress() по их именам;
- создать динамический объект класса путем вызова из DLL соответствующей функции через её указатель, которая возвращает адрес этого объекта;
- вызовы виртуальных методов класса производить по их именам, через указатель на динамический объект;
- уничтожить динамический объект класса путем вызова из DLL соответствующей функции через её указатель с передачей адреса объекта.
Пример. В п. 2. приведено описание заголовочного файла и исходного кода библиотеки MyDLL.dll, содержащей класс MyDLLClass.
Необходимо выполнить следующее:
1. Скорректировать библиотеку MyDLL.dll, а именно:
- дополнить её двумя функциями NewObject() и DestroyObject() для создания и уничтожения динамического объекта класса MyDLLClass;
- объявить в DLL функцию ClMyFunc() виртуальной в классе MyDLLClass;
2. Создать приложение MyDLLApp2.exe, которое явно загрузит указанную DLL, создаст объект класса MyDLLClass, вызвав функцию NewObject(), затем вызовет виртуальные методы класса ClMyFunc(), ClVirtFunc() и уничтожит объект, вызвав функцию DestroyObject().
|
|
Скорректированный заголовочный файл MyDLL.h для MyDLL.dll будет иметь следующий вид:
Файл MyDLL . h - скорректированный
// Условное определение макроса MyDLL_API
#ifdef MyDLL_EXPORTS
#define MyDLL_API __declspec (dllexport)
#else
#define MyDLL_API __declspec (dllimport)
#endif
// Прототип экспортируемой функции MyDLLFunction
MyDLL_API int MyDLLFunction(void);
// Описание экспортируемого класса MyDLLClass
class MyDLL_API MyDLLClass {
public:
MyDLLClass(void); // Конструктор класса
~MyDLLClass(void); // Деструктор класса
// Функция ClMyFunc() объявлена виртуальной
virtual int ClMyFunc(void);
virtual int ClVirtFunc(void); // Виртуальная функция
};
// Описание экспортируемой переменной nMyDLLVar
extern MyDLL_API int nMyDLLVar;
// Прототип экспортируемой функции NewObject()
// для создания динамического объекта класса
MyDLL_API MyDLLClass* NewObject();
// Прототип экспортируемой функции DestroyObject()
// для уничтожения динамического объекта класса
MyDLL_API void DestroyObject(MyDLLClass *);
Файл MyDLL.cpp с исходным кодом библиотеки MyDLL.dll необходимо дополнить описаниями двух новых функций NewObject() и DestroyObject():
Дополнение к файлу MyDLL . cpp
…
// Описание функции NewObject()
MyDLLClass* NewObject()
{
return new MyDLLClass;
}
// Описание функции DestroyObject()
void DestroyObject(MyDLLClass *pObj)
{
delete pObj;
}
В файле MyDLLApp2.cpp с исходным кодом программы необходимо записать следующее:
|
|
Файл MyDLLApp 2. cpp
#include "stdafx.h"
#include "MyDLL.h" …// Явная загрузка библиотеки MyDLL.dllHMODULE hMyDll = LoadLibrary("MyDLL.dll");// Получение адреса функции NewObject() из DLL
MyLibClass* (*pNewObject)();
(FARPROC &) pNewObject = GetProcAddress(hMyDll, "NewObject");
// Создание динамического объекта класса
MyLibClass *pDynObj = pNewObject();
// Вызов виртуальных методов класса
int iRez1 = pDynObj->ClMyFunc();int iRez2 = pDynObj->ClVirtFunc();
// Получение адреса функции DestroyObject() из DLL
void (*pDestroyObject)(MyLibClass *);
(FARPROC &) pDestroyObject = GetProcAddress(
hMyDll, "DestroyObject");
// Уничтожение объекта и выгрузка DLL
pDestroyObject(pDynObj);
FreeLibrary(hMyDll);
Примеры создания и использования DLL
Пример создания динамически подключаемой библиотеки
В качестве примера рассмотрим создание простой динамически подключаемой библиотеки MyLib.dll, содержащей следующие экспортируемые идентификаторы:
- глобальную переменную iMyLibVar целого типа;
- функцию MyLibFunc(), которая выводит диалоговое окно с сообщением;
- класс MyLibClass, который включает приватное свойство x целого типа и открытые методы: конструктор MyLibClass(), деструктор ~MyLibClass(), виртуальные функции SetX(), GetX() и SqrX();
- функцию CreateDynObj(), которая создаёт в куче динамический объект класса MyLibClass;
- функцию DeleteDynObj(), которая уничтожает динамический объект класса MyLibClass.
|
|
Для создания такой библиотеки необходимо подготовить два файла: заголовочный файл MyLib.h и файл с исходным кодом MyLib.cpp. Содержимое этих файлов приведено ниже:
// MyLib . h : Заголовочный файл библиотеки MyLib . dll
// Условное определение макроса MYLIB_API в зависимости от MYLIB_EXPORTS
#ifdef MYLIB_EXPORTS
#define MYLIB_API __declspec(dllexport)
#else
#define MYLIB_API __declspec(dllimport)
#endif
// Описание переменной iMyLibVar, экспортируемой из MyLib.dll
extern MYLIB_API int iMyLibVar;
// Прототип функции MyLibFunc, экспортируемой из MyLib.dll
MYLIB_API void MyLibFunc(PSTR);
// Описание класса MyLibClass, экспортируемого из MyLib.dll
class MYLIB_API MyLibClass {
private:
int x; // Приватная переменная x
public:
MyLibClass(void); // Конструктор класса
~MyLibClass(void); // Деструктор класса
virtual void SetX(int); // Функция для задания значения переменной х
virtual int GetX(void); // Функция для получения значения переменной х
virtual int SqrX(void); // Функция для получения квадрата переменной х
};
// Прототип экспортируемой из MyLib.dll функции CreateDynObj
// для создания в куче динамического объекта класса MyLibClass
MYLIB_API MyLibClass* CreateDynObj();
// Прототип экспортируемой из MyLib.dll функции DeleteDynObj
// для уничтожения динамического объекта класса MyLibClass
MYLIB_API void DeleteDynObj(MyLibClass *);
// MyLib.cpp: Исходный код библиотеки MyLib.dll#include "stdafx.h"// Объявление экспортируемых DLL идентификаторов внешними в формате Cextern "C" { #include "MyLib.h" // Заголовочный файл DLL} BOOL APIENTRY DllMain(HANDLE hModule, DWORD fdwReason, LPVOID lpReserved){ switch (fdwReason) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE;} // Инициализация экспортируемой переменной iMyLibVarint iMyLibVar=0; // Описание функции вывода диалогового окна с сообщением MyLibFunc()void MyLibFunc(PSTR pStr){ MessageBox(NULL,pStr,"Сообщение из DLL-функции MyLibFunc()",MB_OK);} // Описания методов класса согласно их прототипам в MyLib.h// Описание конструктора класса MyLibClassMyLibClass::MyLibClass(){ MessageBox(NULL, "Создание объекта класса MyLibClass", "Сообщение из DLL MyLib.dll", MB_OK); }// Описание деструктора класса MyLibClassMyLibClass::~MyLibClass(){ MessageBox(NULL, "Уничтожение объекта класса MyLibClass", "Сообщение из DLL MyLib.dll", MB_OK); }// Описание виртуальной функции SetX()void MyLibClass :: SetX(int a = 0){ x = a; // Задание значения переменной х}// Описание виртуальной функции GetX()int MyLibClass :: GetX(){ return x; // Получение значения переменной х}// Описание виртуальной функции SqrX()int MyLibClass :: SqrX(){ return x*x; // Получение квадрата переменной х } // Описание функции для создания динамического объекта класса MyLibClassMyLibClass* CreateDynObj(){ return new MyLibClass;}// Описание функции для уничтожения динамического объекта класса MyLibClassvoid DeleteDynObj(MyLibClass *pObject){ delete pObject;}
В заголовочном файле библиотеки MyLib.h после условной компиляции #ifdef … #endif, где определяется макрос MYLIB_API, приведены описания экспортируемых из DLL идентификаторов: глобальной переменной iMyLibVar; функции MyLibFunc(); класса MyLibClass, его свойств и методов; функций CreateDynObj() и DeleteDynObj() для создания и уничтожения динамического объекта класса MyLibClass.
|
|
В файле с исходным кодом библиотеки MyLib.cpp после включения в него стандартного заголовочного файла stdafx.h, с помощью модификатора extern " C " все экспортируемые DLL функции и переменные объявлены внешними в формате C. Это необходимо для того, чтобы в секции экспорта компилятор языка C++ не производил расширение имен, а сохранял их в обычном виде в соответствии с соглашениями языка C. Тем самым в приложениях обеспечивается возможность получения адресов переменных и функций (кроме классов) по их именам для явно загруженной DLL. При неявном подключении DLL такой проблемы не возникает при условии, что исходные коды библиотеки и приложений обрабатываются одним компилятором. Далее в файле MyLib.cpp приведена функция входа в DLL – DllMain() без обработки уведомлений, а также – описания всех функций, входящих в библиотеку и методов класса MyLibClass.
После трансляции и компоновки этих файлов будут созданы два файла – MyLib.dll (динамически подключаемая библиотека) и MyLib.lib (ее библиотека импорта), которые будут размещены в подкаталоге проекта библиотеки …\MyLib\Debug.
Дата добавления: 2019-09-13; просмотров: 122; Мы поможем в написании вашей работы! |
Мы поможем в написании ваших работ!