Почему / когда __declspec( dllimport) не нужен?

В проекте, использующем server.dll и client.exe, у меня есть dllexportредактировать символ сервера с сервера dll, а не dllimportотредактировал его в exe клиента.

Тем не менее приложение связывается и запускается без каких-либо проблем. Является dllimport не нужно то???

Подробности:

У меня есть эта "серверная" DLL:

// server.h
#ifdef SERVER_EXPORTS
  #define SERVER_API __declspec(dllexport)
#else
  #define SERVER_API // =====> not using dllimport!
#endif
class  SERVER_API CServer {
   static long s;
   public:
   CServer();
};

// server.cpp
CServer::CServer(){}

long CServer::s;

и этот исполняемый файл клиента:

#include <server.h>
int main() {
   CServer s;
}

Командная строка сервера:

cl.exe /Od  /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_USRDLL" 
 /D "SERVER_EXPORTS" /D "_UNICODE" /D "UNICODE" /D "_WINDLL" 
 /Gm /EHsc /RTC1 /MDd /Yu"stdafx.h" 
 /Fp"Debug\server.pch" /Fo"Debug\\" /Fd"Debug\vc80.pdb" 
 /W3 /nologo /c /Wp64 /ZI /TP /errorReport:prompt

cl.exe /OUT:"U:\libs\Debug\server.dll" /INCREMENTAL:NO /NOLOGO /DLL 
/MANIFEST /MANIFESTFILE:"Debug\server.dll.intermediate.manifest" 
/DEBUG /PDB:"u:\libs\Debug\server.pdb" 
/SUBSYSTEM:WINDOWS /MACHINE:X86 /ERRORREPORT:PROMPT 
kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib 
shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib

Клиентская командная строка:

cl.exe /Od /I "..\server" 
 /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" 
 /Gm /EHsc /RTC1 /MDd /Fo"Debug\\" /Fd"Debug\vc80.pdb" /W3 /c /Wp64 /ZI /TP 
 .\client.cpp

cl.exe /OUT:"U:\libs\Debug\Debug\client.exe" /INCREMENTAL 
/LIBPATH:"U:\libs\Debug" 
/MANIFEST /MANIFESTFILE:"Debug\client.exe.intermediate.manifest" 
/DEBUG /PDB:"u:\libs\debug\debug\client.pdb" 
/SUBSYSTEM:CONSOLE /MACHINE:X86 
server.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib 
advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib

2 ответа

Решение

Это не обязательно. Это оптимизация, подсказка компилятору, что DLL собирается экспортировать указатель функции напрямую, а не просто запись в IAT библиотеки DLL. Указатель экспортируемой функции для функции с именем foo() будет __imp_foo. Что позволяет генерировать лучший код, сохраняя загрузку указателя функции из IAT и косвенный переход. Это оптимизация времени, а не пространства.

Этот пост содержит подробности.

Мне тоже было интересно об этом. Я также удалил инструкцию __declspec(dllimport) и был очень удивлен, увидев, что dll (gmodule), использующая функции из другой dll (glib), скомпилирована и запущена (в частности, wirehark) без проблем. Вот цитата М.С.:

      __declspec(dllimport) is ALWAYS required to access exported DLL data.

Понятия не имею, почему MS это говорит, потому что на других страницах они заявляют, что инструкция не нужна. Тем не менее, моя библиотека не только работает без dllimport, но я уже много лет не видел символа «__imp», хотя раньше я постоянно натыкался на него (или он на меня). Что случилось с этим? Ответ здесь:

      That's why using __declspec(dllimport) is better: because the linker doesn't generate a thunk if it's not required. There's no thunk and no jmp instruction, so the code is smaller and faster. You can also get the same effect WITHOUT __declspec(dllimport) by using whole program optimization. For more information, see /GL (Whole Program Optimization).

Теперь это имеет смысл. Я использую / GL (+ /LTCG) во всех проектах. Вот и ответ на вопрос по теме

      when is __declspec( dllimport ) not needed?

Когда используется оптимизация всей программы.

Другие вопросы по тегам