Й вариант. Работа с методами класса без использования их номеров



Для реализации этого варианта потребуется выполнить ряд дополнительных действий:

а) в динамически подключаемой библиотеке:

- описать дополнительно две функции для создания и уничтожения динамического объекта класса в 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; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!