ИНФОРМАЦИЯ: Использование в коде _declspec(dllimport) & _declspec(dllexport)

Переводы статьи Переводы статьи
Код статьи: 132044 - Vizualiza?i produsele pentru care se aplic? acest articol.
Развернуть все | Свернуть все

В этой статье

Аннотация

Эта статья дополняет сведения, описанные в следующей статье в Microsoft Knowledge Base:
107501 ИНФОРМАЦИЯ: __export заменены __declspec в 32-разрядных Visual C++
В этой статье обсуждаются преимущества и механизм использования _declspec(dllimport) и _declspec(dllexport) в приложении.

Дополнительная информация

32-Разрядной версии Visual C++ использует _declspec(dllimport) и _declspec(dllexport) заменить ключевое слово __export, ранее использовался в 16-разрядных версиях Visual C++.

Необходимо использовать _declspec(dllimport) для кода для компиляции правильно но применение позволяет компилятору создать код лучшего качества. В компилятор может создать код лучшего качества, потому что он знает точно ли функция существует в библиотеке DLL или нет, поэтому компилятор может создавать коды Пропустите уровень косвенного обращения, которые обычно являются в функции вызов, библиотеке.

С правильнымРазделе EXPORTS DEF-файла, не является _declspec(dllexport) соблюдения дополнительных условий. _declspec(dllexport) был добавлен обеспечивают простой способ для экспорта из функции.EXE или.Библиотеки DLL без использования.DEF-файла.

Оставшаяся часть этой статьи предоставляет достаточно низкоуровневого тщательной обсуждение этих вопросов.

Формат переносимого исполняемого файла Win32 разработан для минимизации числа страницы, которые необходимо прикоснулись к импортов. Чтобы сделать это, он помещает все Импорт адресов для любой программы в одном месте, называется адрес импорта Таблица. Это позволяет загрузчику модифицировать только одна или две страницы, когда доступ к этим imports.

С помощью _declspec(dllimport) для вызовов функций

В следующем примере кода предполагается func1 является функция, которая хранится в Отдельно от библиотеки DLL.EXE-файла, содержащего функцию main().

Без _declspec(dllimport) учитывая этот код:
void main(void) {
    func1();
}
				
компилятор создает код, который выглядит следующим образом:
call func1
				
и компоновщик преобразует вызов в примерно следующим образом:
call 0x4000000         ; The address of 'func1'.
				
Если «func1» существует в другой библиотеке DLL, компоновщик не может разрешить это непосредственно так как нет способа узнать адрес «func1» — в ней. В 16-разрядное средах компоновщик добавляет адрес этого кода в список в.EXE что бы исправление загрузчик, во время выполнения правильный адрес. В 32-разрядной средах компоновщик создает преобразователь, для которой известны адрес. Преобразователь выглядит следующим образом:
   0x40000000:    jmp DWORD PTR __imp_func1
				
Здесь __imp_func1 — это адрес для разъема func1 в адрес импорта Таблица.EXE-файла. Таким образом, все адреса известны компоновщику. В Загрузчик имеет только для обновления.Таблица адресов импорта EXE файла во время загрузки для всех объектов, для правильной работы.

Таким образом, с помощью _declspec(dllimport) предпочтительнее, так как он лучше, если Компоновщик не создавать преобразователь, если его нет. Преобразователи расширяют код большего размера (для систем RISC, она может быть несколько инструкций) и могут ухудшить эффективность кэша. Если сообщить компилятору функция находится в DLL, он может быть создан непрямой вызов.

Так что теперь этот код:
__declspec(dllimport) void func1(void);

void main(void) {
    func1();
}
				
создает следующую инструкцию:
call DWORD PTR __imp_func1
				
Нет отсутствует преобразователь и инструкция не jmp, поэтому код меньшего размера и быстрее.

С другой стороны для вызовов функций в библиотеке DLL не требуется иметь Чтобы использовать непрямой вызов. Вы уже знаете адрес функции. Время и места необходимо загрузить и хранить адрес функции перед косвенный вызов, поэтому прямой вызов всегда быстрее и меньше. Требуется только Чтобы использовать __declspec(dllimport) при вызове функций библиотеки DLL, за пределами самой библиотеке DLL. Не используйте __declspec(dllimport) для функций в библиотеке DLL При построении данной Библиотеки.

С помощью _declspec(dllexport)

Корпорация Майкрософт представила __export в версии 16-разрядный компилятор, чтобы разрешить компилятор автоматически создает имена экспорта и помещает их в .LIB-файл. ЭтотLIB-файл может использоваться так же, как статический.LIB для связи с библиотекой DLL.

Корпорация Майкрософт добавила __declspec(dllexport) для продолжения такого рода. Его предназначено для добавления директивы экспорта файла объекта, поэтому нет необходимости с.DEF-файла.

Данное преимущество особенно заметно при экспорте декорированных C++ имена функций. Поэтому есть не стандартные спецификации для Декорирование имен имя экспортируемой функции может отличаться в разных версиях компилятора. Если Используйте _declspec(dllexport), перекомпиляция библиотеки DLL и зависимые.EXE файлы Это необходимо только для учетной записи изменений соглашение об именовании.

Например, можно сделать порядковые номера NONAME и PRIVATE, большинство директив экспорта только в.DEF-файла, а не способ указания этих атрибутов без.DEF-файла. Тем не менее с помощью _declspec(dllexport) в дополнение к с помощью.DEF-файла не приводит к ошибкам построения.

В качестве ссылки поиск по Win32 WINBASE.Файл заголовка. Он содержит Примеры основной __declspec(dllexport) и __declspec(dllimport) Использование.

С помощью _declspec(dllexport) и _declspec(dllimport) данных

В случае данных с помощью _declspec(dllimport) является удобства товара Удаляет уровень косвенного обращения. При импорте данных из библиотеки DLL, которые по-прежнему Чтобы иметь через таблицы адресов импорта. В Win32 дней до _declspec(dllimport), это означало, что нужно было помнить о необходимости выполнения дополнительный уровень косвенного обращения при доступе к данным, экспортируемой из DLL:
// project.h
#ifdef _DLL     // If accessing the data from inside the DLL
   ULONG ulDataInDll;

else            // If accessing the data from outside the DLL
   ULONG *ulDataInDll;
#endif
				
Затем будет экспортировать данные в вашем.DEF-файла:
// project.def
LIBRARY project
EXPORTS
    ulDataInDll   CONSTANT
				
и доступ к нему вне библиотеки DLL:
if (*ulDataInDll == 0L) {
   // Do stuff here
}
				
Когда помечается данные как __declspec(dllimport), компилятор автоматически создается код косвенного обращения. Больше не нужно беспокоиться о описанные выше действия. Как уже говорилось ранее, следует использовать _declspec(dllimport) объявление данных при построении библиотеки DLL. Функции в библиотеке DLL Таблица адресов импорта не будет использовать для доступа к объекту данных. Таким образом, не будет иметь дополнительный уровень косвенного обращения.

Для автоматического экспорта данных из библиотеки DLL, используйте следующее объявление:
__declspec(dllexport) ULONG ulDataInDLL;
				

С помощью.DEF-файла

Если решено использовать __declspec(dllimport) вместе с.DEF-файла, можно следует изменить.DEF-файла для использования данных вместо КОНСТАНТЫ для уменьшения вероятность того, что неверный код вызовет ошибку:
// project.def
LIBRARY project
EXPORTS
    ulDataInDll   DATA
				
Следующая диаграмма показывает, почему:
Keyword     Emits in the import lib     Exports
CONSTANT    __imp_ulDataInDll           ulDataInDll
            __ulDataInDll

DATA        __imp_ulDataInDll           ulDataInDll
				
С помощью _declspec (dllimport) и КОНСТАНТЫ перечислены версии __imp_ и Внутреннее имя в.Библиотека импорта LIB DLL, созданный для Разрешить явное связывание. Использование данных и _declspec(dllimport) перечислены только __imp_ версия имени.

Если используется КОНСТАНТА, либо из следующих конструкций кода может быть использована для доступа к ulDataInDll:
__declspec(dllimport) ULONG ulDataInDll; /*prototype*/ 
   if (ulDataInDll == 0L)   /*sample code fragment*/ 
				
- или -
ULONG *ulDataInDll;      /*prototype*/ 
if (*ulDataInDll == 0L)  /*sample code fragment*/ 
				
Однако при использовании данных в вашей.DEF-файла только код скомпилирован с следующие определения можно получить доступ к переменной ulDataInDll:
__declspec(dllimport) ULONG ulDataInDll;
if (ulDataInDll == 0L)   /*sample code fragment*/ 
				
Использование КОНСТАНТ более опасными, поскольку если вы забудете использовать дополнительный уровень косвенного обращения потенциально может открыть таблицы адресов импорта указатель на переменную--не саму переменную. Этот тип проблемы часто может проявиться как нарушение прав доступа, так как таблица адресов импорта в настоящее время выполняется только для чтения, компилятор Microsoft и компоновщиков команда разработчиков.

Компоновщик текущего Visual C++ выдает предупреждение при обнаружении CONSTANT в в.DEF-файла для учетной записи для этого случая. Единственным реальным основанием для использования Является КОНСТАНТОЙ, если невозможно перекомпилировать некоторый объектный файл, где файл заголовка не содержит списка dllimport в прототипе.

Ссылки

Visual C++ Books Online предоставить значительный объем документации атрибуты класса хранения dllexport и dllimport. Это включает в себя «Атрибуты dllexport и dllimport» и "с помощью dllimport и dllexport в C++ "разделы в главе «Модификаторы относящиеся к Майкрософт» Справочник по языку C++ и в подразделах «Экспорт символов» «Создание библиотеки DLL для Win32» Глава ссылка приемов программирования. Тщательное список щелкните ссылку поиска электронной документации для «dllimport» или «dllexport».

Дополнительные сведения можно найти следующие статьи в Microsoft База знаний:
90530 Экспорт данных из библиотеки DLL или приложения
107501 ИНФОРМАЦИЯ: __export заменены __declspec в 32-разрядных Visual C++

Свойства

Код статьи: 132044 - Последний отзыв: 21 сентября 2012 г. - Revision: 8.0
Информация в данной статье относится к следующим продуктам.
  • Microsoft Visual C++ 2.0 Professional Edition
  • Microsoft Visual C++ 5.0 Enterprise Edition
  • Microsoft Visual C++ 5.0 Professional Edition
Ключевые слова: 
kbcode kbcompiler kbinfo kbmt KB132044 KbMtru
Переведено с помощью машинного перевода
ВНИМАНИЕ! Перевод данной статьи был выполнен не человеком, а с помощью программы машинного перевода, разработанной корпорацией Майкрософт. Корпорация Майкрософт предлагает вам статьи, переведенные как людьми, так и средствами машинного перевода, чтобы у вас была возможность ознакомиться со статьями базы знаний KB на родном языке. Однако машинный перевод не всегда идеален. Он может содержать смысловые, синтаксические и грамматические ошибки, подобно тому как иностранец делает ошибки, пытаясь говорить на вашем языке. Корпорация Майкрософт не несет ответственности за неточности, ошибки и возможный ущерб, причиненный в результате неправильного перевода или его использования. Корпорация Майкрософт также часто обновляет средства машинного перевода.
Эта статья на английском языке: 132044
Заявление об отказе относительно содержимого статьи о продуктах, поддержка которых прекращена
Эта статья содержит сведения о продуктах, поддержка которых корпорацией Майкрософт прекращена. Поэтому она предлагается как есть и обновляться не будет.

Отправить отзыв

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com