48

In a project using a server.dll and a client.exe, I have dllexported a server symbol from the server dll, and not dllimported 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
11
  • 2
    Good question actually. the MSDN Docs --- msdn.microsoft.com/en-us/library/3y1sfaz2(VS.80).aspx --- didn't enlighten me if there's any benefit over using extern (with correct calling convention and name mangling) and specifying an import library. Commented Dec 20, 2010 at 14:31
  • 3
    __declspec(dllexport) on classes and class members is very, very fragile. What is the purpose of the separate server.dll? Really the only thing __declspec(dllexport) on a class does well is reducing process startup I/O, when it is paired with /delayload:server.dll. Any other perceived advantages (e.g. imagined ability to patch DLL logic without recompiling the application) are actually violations of the One-Definition-Rule and unreliable. Commented Dec 20, 2010 at 14:38
  • 3
    @xtofl: Decoupling is good, and the source code may in fact be decoupled. But __declspec(dllexport) on classes and class members causes the binaries to be closely coupled. In other words, you'd have the same level of coupling, with much less deployment burden, by using static libraries and no __declspec(dllexport) anywhere. Commented Dec 20, 2010 at 14:58
  • 3
    @Sergey: You'd be better off by having all code within a single .DLL module, exporting only plain C functions corresponding to the main function for each of the 7 applications (or even arguments to a single .exe, ala busybox). On Windows at least, which is the platform we're discussing here, Qt does not provide binary compatibility. You have to build the Qt library yourself using the particular compiler and command-line options used by your application, in order to avoid violating ODR. In which case you again might as well be using a static library. Commented Dec 20, 2010 at 15:57
  • 2
    @marshalcraft this is not a blog - save your rants for elsewhere. Please :). Commented Jul 26, 2017 at 13:32

2 Answers 2

62

__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

Sign up to request clarification or add additional context in comments.

4 Comments

From the linked article: <quote>For data, it is required for correctness.</quote>
Thanks! You pointed to the right blog post. Your phrasing is a bit confusing, though - I thought that the importing source would result in a call to the __imp_foo thunk in the importing code.
I've fixed the details as per the blog post. dllimport is completely on the client-side which has the IAT and not on the DLL-side which only has an EAT since it just exports. Thanks for the answer and the link!
2

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.