Reputation: 41509
In a project using a server.dll and a client.exe, I have dllexport
ed a server symbol from the server dll, and not dllimport
ed it into the client exe.
Still, the application links, and starts, without any problem. Is dllimport
not needed, then???
Details:
I have this 'server' 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;
and this client executable:
#include <server.h>
int main() {
CServer s;
}
The server command line:
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
Client command line:
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
Upvotes: 46
Views: 14500
Reputation: 941208
__declspec(dllimport)
is a client-side MSVC attribute that can be specified for imported code and data.
It isn't required for code. It is an optimization; a client-side compiler hint that a function call isn't direct but imported. The imported function pointer for a function named foo()
will be __imp_foo
. Without the hint, a thunk is created to load the address in __imp_foo
and jump to it. With the hint the thunk is skipped and an indirect call through the IAT1 entry is generated i.e. the thunk is inlined. It is a time optimization, not space.
It's required for data that's imported from a DLL.
This blog post has the details.
1: Import Address Table of a program
Upvotes: 60
Reputation: 147
I was wondering about this too. I also removed the __declspec(dllimport) instruction and was very surprised to see that a dll (gmodule) relying on functions in another dll (glib) compiled and ran (in wireshark in particular) without problems. Here's a quote by MS:
__declspec(dllimport) is ALWAYS required to access exported DLL data.
No idea why MS says this, because on other pages they state the instruction is not necessary. Regardless, not only does my library run without dllimport, but I haven't seen an "__imp" symbol in ages, while formerly I was constantly stumbling upon it (or it on me). What happened to it? The answer is here:
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).
Now it makes sense. I am using /GL (+ /LTCG) on all projects. So that's the answer to the topic question
when is __declspec( dllimport ) not needed?
When whole program optimization is utilised.
Upvotes: 2