.def files C/C++ DLLs

My understanding is that .def files provide an alternative to the __declspec(dllexport) syntax, with the additional benefit of being able to explicitly specify the ordinals of the exported functions. This can be useful if you export some functions only by ordinal, which doesn't reveal as much information about the function itself (eg: many of the OS internal DLL's export functions only by ordinal).

See the reference page.

Note that the names in the .def file must match the names in the binary. So if you using C or C++ with 'extern "C" { ... }', the names will not be mangled; otherwise you must use the correct mangled names for the specific version of the compiler used to generate the DLL. The __declspec() function does this all automatically.


I find the use of both __declspec(dllexport) and the .def file together to be useful in creating portable DLLs, i.e. DLLs that can be called from code compiled with a different compiler or with different compiler settings.

Just putting __declspec(dllexport) on your function declarations will cause those functions to be "exported" by your DLL (at least on Windows) so that they can be called from outside the DLL.

However, adding to the build a .def file that lists all of your exported functions lets you stop Microsoft compilers (for example) from adding a leading underscore and trailing parameter-width information to the exported function name (at least when combined with the __stdcall directive, also useful for portability). E.g. the function declaration

void foo(int i);

could end up being exported as "_foo@4" if you aren't careful about calling convention and .def file usage.

Keeping the exported function names in the symbol table free of such name-decoration comes in really handy when making GetProcAddress() calls as part of loading and hooking into a DLL explicitly at runtime. i.e. to get a pointer to the above function foo() (assuming it was exported at all) at runtime, you ideally just want to call:

HANDLE dllHandle = LoadLibrary("mydll.dll");
void* fooFcnPtr = GetProcAddress(dllHandle, "foo");

With some appropriate error case checking of course!

Use of a .def file plus __stdcall, __declspec(dllexport) and extern "C" on your function declarations when building your DLL will ensure that the above client-side code will work for a wide range of compilers and compiler settings.

Tags:

C++

C

Dll