МегаПредмет

ПОЗНАВАТЕЛЬНОЕ

Сила воли ведет к действию, а позитивные действия формируют позитивное отношение


Как определить диапазон голоса - ваш вокал


Игровые автоматы с быстрым выводом


Как цель узнает о ваших желаниях прежде, чем вы начнете действовать. Как компании прогнозируют привычки и манипулируют ими


Целительная привычка


Как самому избавиться от обидчивости


Противоречивые взгляды на качества, присущие мужчинам


Тренинг уверенности в себе


Вкуснейший "Салат из свеклы с чесноком"


Натюрморт и его изобразительные возможности


Применение, как принимать мумие? Мумие для волос, лица, при переломах, при кровотечении и т.д.


Как научиться брать на себя ответственность


Зачем нужны границы в отношениях с детьми?


Световозвращающие элементы на детской одежде


Как победить свой возраст? Восемь уникальных способов, которые помогут достичь долголетия


Как слышать голос Бога


Классификация ожирения по ИМТ (ВОЗ)


Глава 3. Завет мужчины с женщиной


Оси и плоскости тела человека


Оси и плоскости тела человека - Тело человека состоит из определенных топографических частей и участков, в которых расположены органы, мышцы, сосуды, нервы и т.д.


Отёска стен и прирубка косяков Отёска стен и прирубка косяков - Когда на доме не достаёт окон и дверей, красивое высокое крыльцо ещё только в воображении, приходится подниматься с улицы в дом по трапу.


Дифференциальные уравнения второго порядка (модель рынка с прогнозируемыми ценами) Дифференциальные уравнения второго порядка (модель рынка с прогнозируемыми ценами) - В простых моделях рынка спрос и предложение обычно полагают зависящими только от текущей цены на товар.

Экспортирование функций из DLL





Чтобы приложение могло обращаться к функциям динамической библиотеки, каждая из них должна занимать строку в таблице экспортируемых функций DLL. Есть два способа занести функцию в эту таблицу на этапе компиляции.

Метод __declspec (dllexport)

Можно экспортировать функцию из DLL, поставив в начале ее описания модификатор __declspec (dllexport) . Кроме того, в состав MFC входит несколько макросов, определяющих __declspec (dllexport), в том числе AFX_CLASS_EXPORT, AFX_DATA_EXPORT и AFX_API_EXPORT.

Метод __declspec применяется не так часто, как второй метод, работающий с файлами определения модуля (.def), и позволяет лучше управлять процессом экспортирования.

Файлы определения модуля

Синтаксис файлов с расширением .def в Visual C++ достаточно прямолинеен, главным образом потому, что сложные параметры, использовавшиеся в ранних версиях Windows, в Win32 более не применяются. Как станет ясно из следующего простого примера, .def-файл содержит имя и описание библиотеки, а также список экспортируемых функций:

MyDLL.def

LIBRARY "MyDLL"

DESCRIPTION 'MyDLL - пример DLL-библиотеки'

EXPORTS

MyFunction @1

В строке экспорта функции можно указать ее порядковый номер, поставив перед ним символ @. Этот номер будет затем использоваться при обращении к GetProcAddress (). На самом деле компилятор присваивает порядковые номера всем экспортируемым объектам. Однако способ, которым он это делает, отчасти непредсказуем, если не присвоить эти номера явно.

В строке экспорта можно использовать параметр NONAME. Он запрещает компилятору включать имя функции в таблицу экспортирования DLL:

MyFunction @1 NONAME

Иногда это позволяет сэкономить много места в файле DLL. Приложения, использующие библиотеку импортирования для неявного подключения DLL, не "заметят" разницы, поскольку при неявном подключении порядковые номера используются автоматически. Приложениям, загружающим библиотеки DLL динамически, потребуется передавать в GetProcAddress порядковый номер, а не имя функции.

При использовании вышеприведенного def-файл описания экспортируемых функций DLL-библиотеки может быть,например, не таким:

#define EXPORT extern "C" __declspec (dllexport)

EXPORT int CALLBACK MyFunction(char *str);

a таким:

extern "C" int CALLBACK MyFunction(char *str);

Экспортирование классов

Создание .def-файла для экспортирования даже простых классов из динамической библиотеки может оказаться довольно сложным делом. Понадобится явно экспортировать каждую функцию, которая может быть использована внешним приложением.

Если взглянуть на реализованный в классе файл распределения памяти, в нем можно заметить некоторые весьма необычные функции. Оказывается, здесь есть неявные конструкторы и деструкторы, функции, объявленные в макросах MFC, в частности _DECLARE_MESSAGE_MAP, а также функции, которые написанные программистом.

Хотя можно экспортировать каждую из этих функций в отдельности, есть более простой способ. Если в объявлении класса воспользоваться макромодификатором AFX_CLASS_EXPORT, компилятор сам позаботится об экспортировании необходимых функций, позволяющих приложению использовать класс, содержащийся в DLL.

Память DLL

В отличие от статических библиотек, которые, по существу, становятся частью кода приложения, библиотеки динамической компоновки в 16-разрядных версиях Windows работали с памятью несколько иначе. Под управлением Win 16 память DLL размещалась вне адресного пространства задачи. Размещение динамических библиотек в глобальной памяти обеспечивало возможность совместного использования их различными задачами.



В Win32 библиотека DLL располагается в области памяти загружающего ее процесса. Каждому процессу предоставляется отдельная копия "глобальной" памяти DLL, которая реинициализируется каждый раз, когда ее загружает новый процесс. Это означает, что динамическая библиотека не может использоваться совместно, в общей памяти, как это было в Winl6.

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

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

#pragma data_seg(".myseg")

int sharedlnts[10] ;

// другие переменные общего пользования

#pragma data_seg()

#pragma comment(lib, "msvcrt" "-SECTION:.myseg,rws");

Все переменные, объявленные между директивами #pragma data_seg(), размещаются в сегменте .myseg. Директива #pragma comment () - не обычный комментарий. Она дает указание библиотеке выполняющей системы С пометить новый раздел как разрешенный для чтения, записи и совместного доступа.

Полная компиляция DLL

Если проект динамической библиотеки создан с помощью AppWizard и .def-файл модифицирован соответствующим образом - этого достаточно. Если же файлы проекта создаются вручную или другими способами без помощи AppWizard, в командную строку редактора связей следует включить параметр /DLL. В результате вместо автономного выполняемого файла будет создана библиотека DLL.

Если в .def-файле есть строка LIBRART, указывать явно параметр /DLL в командной строке редактора связей не нужно.

Для MFC предусмотрен ряд особых режимов, касающихся использования динамической библиотекой библиотек MFC. Этому вопросу посвящен следующий раздел.

DLL и MFC

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

Имеется два уровня использования структуры MFC в DLL. Первый из них - это обычная динамическая библиотека на основе MFC, MFC DLL (regular MFC DLL). Она может использовать MFC, но не может передавать указатели на объекты MFC между DLL и приложениями. Второй уровень реализован в динамических расширениях MFC (MFC extensions DLL). Использование этого вида динамических библиотек требует некоторых дополнительных усилий по настройке, но позволяет свободно обмениваться указателями на объекты MFC между DLL и приложением.

Обычные MFC DLL

Обычные MFC DLL позволяют применять MFC в динамических библиотеках. При этом приложения, обращающиеся к таким библиотекам, не обязательно должны быть построены на основе MFC. В обычных DLL можно использовать MFC любым способом, в том числе создавая в DLL новые классы на базе классов MFC и экспортируя их в приложения.

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

Если приложению необходимо обмениваться с DLL указателями на объекты классов MFC или их производных, нужно использовать расширение DLL, описанное в следующем разделе.

Архитектура обычных DLL рассчитана на использование другими средами программирования, такими как Visual Basic и PowerBuilder.

При создании обычной библиотеки MFC DLL с помощью AppWizard выбирается новый проект типа MFC AppWizard (dll). В первом диалоговом окне мастера приложений необходимо выбрать один из режимов для обычных динамических библиотек: "Regular DLL with MFC statistically linked" или "Regular DLL using shared MFC DLL". Первый предусматривает статическое, а второй - динамическое подключение библиотек MFC. Впоследствии режим подключения MFC к DLL можно будет изменить с помощью комбинированного списка на вкладке "General" диалогового окна "Project settings".

Управление информацией о состоянии MFC

В каждом модуле процесса MFC содержится информация о его состоянии. Таким образом, информация о состоянии DLL отлична от информации о состоянии вызвавшего ее приложения. Поэтому любые экспортируемые из библиотеки функции, обращение к которым исходит непосредственно из приложений, должны сообщать MFC, какую информацию состояния использовать. В обычной MFC DLL, использующей динамические библиотеки MFC, перед вызовом любой подпрограммы MFC в начале экспортируемой функции нужно поместить следующую строку:

AFX_MANAGE_STATE(AfxGetStaticModuleState()) ;

Данный оператор определяет использование соответствующей информации о состоянии во время выполнения функции, обратившейся к данной подпрограмме.





©2015 www.megapredmet.ru Все права принадлежат авторам размещенных материалов.