The Ultimate (DLL) Header File

Here is the ultimate header file that makes multiple declaration compiler errors a thing of the past.

Introduction

Efficient and appropriate use of header files requires a few tricks. If you simply define a set of functions, everything works fine. No problems. If the file is included more than once because of a complex #include chain, you get redundant declarations. Most compilers, including the Microsoft C/C++ compilers, simply ignore these redundant function and variable declarations. However, if there are any class, typedef, struct, or some other declarations, the compiler will complain bitterly if they are seen twice, claiming they are duplication declarations. It does not choose to see if the structures actually are identical. So there is an idiom to avoid duplication declarations, which is to put the entire contents of the header file in an #ifndef, skipping the body if a symbol defined within the body is already defined. This works acceptably well for short files, but is a performance disaster for lengthy files, since each line of the file must be read. For standard header files, precompiled headers work well in eliminating this problem, but it is harder to justify putting your own headers into a precompiled header file since the effects of a simple change result in a massive recompilation (stdafx.h has to be recompiled). Microsoft has added a #pragma that means the header file is read only once. All of this is shown in detail below.

DLL Headers: Additional Complexity

When constructing a DLL, you need a header file to interface to it. However, the obvious solutions do not work as expected. For example, if you declare a function in a fashion so as to export it, you need to add __declspec(dllexport) to its declaration, and if you don't want name mangling, particularly important if you expect to use the DLL with straight C code as well as C++, you need to define it in the .cpp file as

extern"C"__declspec(dllexport) function-header
{
// ... whatever
}

The problem with this approach is that the obvious solutions to the header file don't work.

The First Wrong Approach

The first attempt you might make is to declare, in the .h file

extern"C"function-prototype; // incorrect

This doesn't work because the compiler will complain that the prototype is incompatible with the declaration. What causes this is the prototype lacks the __declspec(dllexport) declaration. So, you say, I'll just add that in. So you get

extern"C"__declspec(dllexport) function-prototype; // incorrect

This doesn't work for a different reason. Although you will no longer get a warning when you compile the DLL, you will get a warning when you compile the application, because the declaration __declspec(dllexport) is incompatible with the use of the function call.

The Second Wrong Approach

At this point a couple workarounds present themselves. The first one you might consider is to use two header files, one of which has the __declspec(dllexport), and the other of which does not. This is a Bad Idea. The reason is that you lose the consistency checking you would get if you include the same header file into both the DLL compilation and the client compilation. For example, if you change the function to have a different parameter type, the compiler will complain unless you change the DLL's header file prototypes to correspond. But in this case, the DLL header file is completely useless, and might as well not exist, because there is a completely separate header file for the client. It remains uncorrected, and there is no cross-check against the actual module. You lose.

A workable but inconvenient approach

At this point, you could remove the __declspec(dllexport) declarations entirely. This means your one-and-only header file will be consistent with the source, but, whoops, the symbols are not exported. To get around this, you can add either the /exports:function command line switch to the linker command line, or use a .def file and add the function name to the EXPORTS section. This is a valid, correct solution, and it works, but you will find that it quickly becomes inconvenient, because you have to remember to add the function name declaration to the /exports switch or add the name to the .def file. Anyone who did DLLs or Windows programming in Win16 in the days before the __export keyword was added to that language will remember how bad this was. Those of you who did not, take our word for it, it was a real royal pain to deal with this. So I'm disinclined to use this solution unless there are other compelling reasons, which there rarely are.

The Ultimate Header File

This is a model which I have cut-and-pasted many times for every DLL I've built in recent years. I've added some comments to help explain and show visually what is going on, and you will probably want to remove these before actually using it.

The uniquename name is something of your own choice. It could be a simple text string, e.g., _DEFINED_MYDLL_HEADER, or you could use GUIDGEN to create a GUID. If you use GUIDGEN, create a "Registry Entry" format, which is

{EBE7C480-A601-11d4-BC36-006067709674}

Remove the { }s and replace the hyphens with underscores. This would give you a symbol like

_DEFINED_EBE7C480_A601_11d4_BC36_006067709674

which guarantees that you will never, ever have a conflict with any other header file.

If the header file is actually processed, this is the traditional C idiom to keep it from being processed twice. The first time the file is included, the symbol _DEFINED_uniqueheadername is not defined, so the file is processed. The first thing it does is declare that symbol, so that in subsequent inclusions, the entire body of the file is skipped.

This is a #pragma which is defined only for C compilers version 10.00 and later (note that the C compiler version and the VC++ version are not related numbers). If this #pragma is implemented, the inclusion of this file in a compilation creates an entry in an "included files table" for that compilation. Subsequent attempts to include this file in the same compilation first check this table, and if the filename is the same, the compiler doesn't even bother to open the file. However, you can't eliminate the contour 1 test, because this #pragma, for reasons best known only to its implementor, is case sensitive in the file name, even though the file name of the underlying operating system is case insensitive. It seems utterly silly that we should have two discrete behaviors, but since when has rationality and common sense affected what some programmers do?

This contour is required to make the header file compatible with both C and C++. It assumes that you want C compatibility, and therefore that the function names should not have C++ "name mangling" applied. The downside of this is that you lose the ability to overload functions based on parameter types. If you are doing a C++-only DLL, you would not use this contour, and you would also eliminate contour 5. The __cplusplus symbol is defined for a C++ compilation but undefined for a C compilation.

This is a funny contour. The #if/#else/#endif contour decides which form of __declspec to use for the declaration. The scope of the effect of this contour actually projects beyond the conditional and extends to the #undef, during which the symbol LIBSPEC is defined. Strictly speaking, you do not need to do the __declspec(dllimport); you could just define LIBSPEC as an empty macro. However, declaring __declspec(dllimport) does same one or two instructions on the linkage when it is finally resolved. Since, using this method, it costs nothing to add this slight efficiency, why not? Note that contour 4 is not needed for non-DLL files.

This is the matching close brace to the structure created in contour 3. If you are doing a C++-only DLL, you would eliminate this as well as contour 3.

Now, in the DLL itself, you have to do one thing: you must declare the _COMPILING_uniquename symbol before the #include. After that, you simply declare the function as shown.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

The vendor of the DLL should provide the prototypes. If the vendor is Microsoft, you will find the headers documented in the MSDN. If it is some random DLL for which you don't have a source license for the header files, there is no good way to figure this out.

This is called an "include guard" and means that if you include the header file twice the second inclusion will effectively be ignored. This can be handled in Microsoft compilers by the #pragma once directive, but if you want platform independence the include guards are still required.

Thanks a lot for your answer.
The reason why I am asking, is because the auto generaed DLL code by VS with the option of "symbol output" also include a _COMPILING_header like you have mentioned,#ifdef MSDLL_EXPORTS
#define MSDLL_API __declspec(dllexport)
#else
#define MSDLL_API __declspec(dllimport)
#endif
but there is no #define MSDLL_EXPORTS in its relative "MSDLL.cpp" and it still can be compiled without any error. After your explaination, I finally found it was defined in property|C/C++|preprocessor.

I have an application that potentially can use two different versions of a hardware card. The two cards each came with their own import lib and DLL which have different names depending which card is being used.

From a s/w API point of view, the function calls in each DLL have the same name and purpose; they just come from different libraries because one card is an ISA bus and the other is PCI.

I know it is possible to load a DLL at runtime, but how do I establish the proper link lib? Do I need to use the LoadLibray call and resolve each funtion as a pointer? or is there an easier way?

You would not use implicit dynamic linking in such a case. You would use explicit dynamic linking, using LoadLibrary. Consequently, no .lib file is involved, and would not make sense.

And yes, you must use LoadLibrary and resolve each function as a pointer.

I'm not sure why the DLL makes a difference, because in Windows, a DLL cannot access hardware (it can in MS-DOS, such as Win9x, but this technology is very, very dead). It sounds more like you need to load a device driver, and in a modern system, that is implicit in the plug-and-play mechanism.

Well, I haven't looked into this issue deeply enough to answer that. My app is part of a manufacturing testing system; the card in question measures time intervals between signals presented at two inputs on the card. All the sample s/w that came with the card links with an import lib and requires a companion DLL to run. My current systems are running under win98se, but the PCI device comes with support for everything from win95 to XP. Installing the driver s/w added a .vxd and a .sys file in addition to the DLL, so I'm assuming they're for accessing h/w under a more modern, protected o/s such as XP. From a s/w point of view, the h/w API is simple function calls; there is no loading of a device driver in any of the sample apps that came with the card.

Perhaps yes, if you don't mind spending an IMMENSE amount of effort to do it, and even then success is problematic. After all, it's just code, and can be manipulated. For example, read the PE format, disassemble the subroutine, rebuild it as a .lib file. Of course, this only works if the DLL has no internal state, or doesn't share data segments, or isn't a standard Microsoft DLL, or someone else's standard DLL.

Practically, it is impossible. Don't waste your time. I think even asking the question is silly.

I have no idea why there is a sudden rise in opposition to DLLs, but this is a poor way of dealing with the problem. What, pray tell, is wrong with using DLLs?

Perhaps the best advice I can give on this topic, since I've seen it so often in the last month, is "get over it". Use DLLs. They are a tool. Use them, take advantage of them.

Note: most objections to DLLs are silly. Some are stupid. Some are simply exhibiting total cluelessness. I have yet to see a meaningful objection. Perhaps your next question will be "how can I eliminate subroutines from C so I can write one big program and not have all those calls?"

And finally, no. While you can include a DLL in an executable as a resource, it has to be extracted into a .DLL file (that is then explicitly loaded) before it can be used.

Please explain why DLLs are a bad idea...

If I seem abrupt, it is that I have lost patience with this question. This must be the sixth time I've had to answer it in the last few weeks.

Man, I wish I had had this two years ago, when I had to struggle through straightening out all the mess of dllexport vs. dllimport.

Here is a two suggestion for further improvement: Add

#if !defined(_COMPILING)
# pragma comment(lib, IMPLIB_NAME_)

IMPLIB_NAME_ can be defined in terms of other preprocessor macros, so you can automagically link with the appropriate import library (debug or release, unicode or mbcs) simply by including this header.