Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Shpora_ROD_1.docx
Скачиваний:
1
Добавлен:
01.03.2025
Размер:
1 Мб
Скачать
☆

2. Использование динамической библиотеки. Экспорт функций из библиотеки. Загрузка и выгрузка dll

Динамически подсоединяемая библиотека (DLL - Dynamic-Link Library). DLL для компонента — сервер, или средство доставки. Компонент — это набор интерфейсов, которые реализованы в DLL. В свою очередь, интерфейс DLL — это набор функций, экспортируемых ею.

Загрузка DLL в адресное пространство клиента. Клиент может загрузить DLL в свое адресное пространство и получить адрес CreateInstance с помощью функций LoadLibrary и GetProcAddress. Имея этот адрес, клиент создает компонент и получает указатель на его IUnknown.

Паспорт функции LoadLibrary:

HINSTANCE LoadLibrary(

LPCTSTR lpLibFileName

);

где HINSTANCE - описатель загруженной DLL; lpLibFileName - Имя файла DLL

Этот метод тесно привязывает клиент к реализации компонента, т.к. он должен знать имя DLL, в которой реализован компонент. Это не позволяет перемещать компонент из одной DLL в другую или из одной директории в другую.

Паспорт функции GetProcAddress:

FARPROC GetProcAddress(

HMODULE hModule,

LPCSTR lpProcName

}

где hModule – описатель модуля DLL, lpProcName - имя экспортируемой из DLL функции; возвращаемое значение – адрес экспортируемой функции.

Пример использования функций:

typedef IUnknown* (*FUNPTR)();

IUnknown* CallCreateInstance(char* name) {

HINSTANCE hComponent = LoadLibrary(name);

if (hComponent == NULL) return NULL;

FUNPTR CreateInstance =

(FUNPTR)::GetProcAddress(hComponent, "CreateInstance");

return CreateInstance();

}

Загрузка DLL посредством библиотеки COM.

Все клиенты и компоненты СОМ выполняют много типовых операций. Эти операции стандартизируются библиотекой функций СОМ.

Для инициализации библиотеки процесс должен вызвать функцию CoInitialize, прежде чем использовать ее функции. Когда процесс завершает работу с библиотекой СОМ, он должен вызвать CoUninitialize. Прототипы этих функций:

HRESULT CoInitialize(void* reserved);

void CoUninitialize();

Параметр reserved должно иметь значение NULL. Библиотека СОМ требует инициализации только один раз для каждого процесса. При завершении работы с библиотекой вызывается функция CoUninitialize. СОМ инициализируется в EXE, а не в DLL, следовательно, она инициализируется клиентом, но не сервером.

Для создания компонентов в библиотеке СОМ служит функция CoCreateInstance, которая, получив CLSID, создает экземпляр соответствующего компонента и возвращает интерфейс этого экземпляра. Для идентификации компонента функция CoCreateInstance использует не строку с именем файла библиотеки DLL, а идентификатор класса GUID, описываемый посредством типа CLSID, отличающегося от типа идентификатора интерфейса IID. Объявление CoCreateInstance:

HRESULT __stdcall CoCreateInstance(

const CLSID& clsid,IUnknown* pUnknownOuter,

DWORD dwClsContext,const IID& iid,void** ppv);

где clsid – идентификатор компонента; pUnknownOuter – указатель на внешний компонент (используется для агрегирования компонентов); dwClsContext - контекст исполнения компонента (значение CLSCTX_INPROC_SERVER указывает на то, что клиент принимает только компоненты, реализованные в DLL и исполняются в одном процессе); iid – идентификатор запрашиваемого интерфейса; ppv - указатель на запрашиваемый интерфейс.

Функция CoCreateInstance создает и использует фабрику класса для экспортирования запрашиваемого компонента из библиотеки DLL. Фабрика класса — это компонент, единственной задачей которого является создание других компонентов. Экспортирование компонента и управление подключением библиотеки выполняется посредством функций DllGetClassObject и DllCanUnloadNow. Соответствующий .def файл, используемый для создания динамической библиотеки компонента имеет вид:

LIBRARY MyServer.dll

EXPORTS

DllGetClassObject @1 PRIVATE

DllCanUnloadNow @2 PRIVATE

Определение функций DllGetClassObject и DllCanUnloadNow выполняется в процессе написания кода компонента и соответствующей фабрики класса.

Задача - Дать пример объявления компонента на языке С++ в модели COM

interface IType_1: IUnknown {

virtual void __stdcall operT1(int, int, int*) = 0;

};

interface IType_2: IUnknown {

virtual void __stdcall operT2(int, int, int*) = 0;

};

class COMP: public IType_1, public IType_2 {

public: // IUnknown

virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv);

virtual ULONG __stdcall AddRef();

virtual ULONG __stdcall Release();

COMP();

~COMP();

//IType_1

virtual void __stdcall operT1(int a, int b, int* c);

//IType_2

virtual void __stdcall operT2(int a, int b, int* c);

private:

long m_cRef;//счетчик ссылок

};

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]