Importing Using DEF Files
If you choose to use __declspec(dllimport)
along with a .def file, you should change the .def file to use DATA in place of CONSTANT to reduce the likelihood that incorrect coding will cause a problem:
// project.def
LIBRARY project
EXPORTS
ulDataInDll DATA
The following table shows why.
Keyword | Emits in the import library | Exports |
---|---|---|
CONSTANT |
_imp_ulDataInDll , _ulDataInDll |
_ulDataInDll |
DATA |
_imp_ulDataInDll |
_ulDataInDll |
Using __declspec(dllimport)
and CONSTANT lists both the imp
version and the undecorated name in the .lib DLL import library that is created to allow explicit linking. Using __declspec(dllimport)
and DATA lists just the imp
version of the name.
If you use CONSTANT, either of the following code constructs can be used to access ulDataInDll
:
__declspec(dllimport) ULONG ulDataInDll; /*prototype*/
if (ulDataInDll == 0L) /*sample code fragment*/
-or-
ULONG *ulDataInDll; /*prototype*/
if (*ulDataInDll == 0L) /*sample code fragment*/
However, if you use DATA in your .def file, only code compiled with the following definition can access the variable ulDataInDll
:
__declspec(dllimport) ULONG ulDataInDll;
if (ulDataInDll == 0L) /*sample code fragment*/
Using CONSTANT is more risky because if you forget to use the extra level of indirection, you could potentially access the import address table's pointer to the variable — not the variable itself. This type of problem can often manifest as an access violation because the import address table is currently made read-only by the compiler and linker.
The current MSVC linker issues a warning if it sees CONSTANT in the .def file to account for this case. The only real reason to use CONSTANT is if you cannot recompile some object file where the header file did not list __declspec(dllimport)
on the prototype.