Determining Which Exporting Method to Use
To determine which method to use to export functions (a .def file or the __declspec(dllexport) keyword), answer the following questions:
Will you be continuing to add additional exported functions?
Who is using your DLL? For example, is it a third-party DLL used by many executables that you cannot rebuild or is the DLL used only by applications that you can easily rebuild?
Exporting functions in a .def file gives you control over what the export ordinals are. When you add additional exported functions to your DLL, you can assign them higher ordinal values (higher than any other exported function). When you do this, applications using implicit linking do not have to relink with the new import library that contains the new functions. This is very important, for example, if you are designing a third-party DLL for use by many applications. You can continue to enhance your DLL by adding additional functionality while at the same time ensuring that existing applications continue to work properly with the new DLL. The MFC DLLs are built using .def files.
Another advantage to using a .def file is that you can export functions using the NONAME attribute, which places only the ordinal in the exports table in the DLL. For DLLs with a large number of exported functions, using the NONAME attribute can reduce the size of the DLL file. For information about writing a module definition statement, see Rules for Module-Definition Statements. For more information about ordinal export, see Exporting Functions from a DLL by Ordinal Rather Than by Name.
The major disadvantage of using a .def file is that if you are exporting functions in a C++ file, you either have to place the decorated names in the .def file or define your exported functions with standard C linkage by using extern "C" to avoid the name decoration done by the compiler.
If you need to place the decorated names in the .def file, you can obtain them by using the DUMPBIN tool or by using the linker /MAP option. Note that the decorated names produced by the compiler are compiler specific. If you place the decorated names produced by the Visual C++ compiler into a .def file, applications that link to your DLL must also be built using the same version of Visual C++ so that the decorated names in the calling application match the exported names in the DLL's .def file.
Using __declspec(dllexport) is convenient because you do not have to worry about maintaining a .def file and obtaining the decorated names of the exported functions. This method is suitable if, for example, you are designing a DLL for use with an application that you control. If you rebuild the DLL with new exports, you also have to rebuild the application because the decorated names for exported C++ functions might change if you recompile with a different version of the compiler.