Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Импорт вызовов функций с помощью
Создание заметок к вызовам с помощью __declspec(dllimport) может ускорить их работу.
__declspec(dllimport) всегда требуется для доступа к экспортированным данным библиотеки DLL.
Импорт функции из библиотеки DLL
В следующем примере кода показано, как использовать __declspec(dllimport) для импорта вызовов функций из библиотеки DLL в приложение. Предположим, что func1 — это функция, которая находится в библиотеке DLL, отделенной от исполняемого файла, который содержит функцию main.
Без __declspec(dllimport) с учетом этого кода:
int main(void)
{
func1();
}
компилятор формирует код, аналогичный следующему:
call func1
и компоновщик преобразует вызов в нечто вроде следующего:
call 0x4000000 ; The address of 'func1'.
Если func1 существует в другой библиотеке DLL, компоновщик не сможет разрешить этот адрес напрямую, поскольку он не имеет возможности узнать, какой адрес присвоен func1. В 32-разрядных и 64-разрядных средах компоновщик создает преобразователь по известному адресу. В 32-разрядной среде преобразователь выглядит следующим образом:
0x40000000: jmp DWORD PTR __imp_func1
Здесь __imp_func1 — это адрес для слота func1 в таблице адресов импорта исполняемого файла. Все эти адреса известны компоновщику. Загрузчику необходимо обновить таблицу адресов импорта исполняемого файла во время загрузки, чтобы все работало правильно.
Вот почему использование __declspec(dllimport) предпочтительнее: компоновщик не создает преобразователь, если он не требуется. Преобразователи усложняют код (в системах RISC это может быть несколько инструкций), что может привести к снижению производительности кэша. Если сообщить компилятору, что функция находится в библиотеке DLL, она может создать косвенный вызов.
Теперь этот код:
__declspec(dllimport) void func1(void);
int main(void)
{
func1();
}
создает следующую инструкцию:
call DWORD PTR __imp_func1
Нет ни преобразователя, ни инструкции jmp, поэтому код будет меньше и быстрее. Также можно получить тот же результат без __declspec(dllimport) с помощью оптимизации всей программы. Дополнительные сведения см. в разделе /GL (оптимизация всей программы).
Для вызовов функций в библиотеке DLL не требуется использовать косвенный вызов. Компоновщик уже знает адрес функции. Загрузка и сохранение адреса функции перед прямым вызовом занимает дополнительное время и место. Прямой вызов всегда выполняется быстрее и проще. Вам необходимо использовать __declspec(dllimport) только при вызове функций DLL извне самой библиотеки DLL. Не используйте __declspec(dllimport) в функциях внутри библиотеки DLL при построении этой библиотеки DLL.