
Creating DLLs in Windows
Submitted by gazihan on Tue, 2008-11-11 23:53.I've always seen and hated those weird macros that preceded functions of header files. Why couldn't they be clean and simple? I hated them because I didn't know much about them, they seemed arbitrary, prone to error, non-standard, no way of knowing the real motivation behind.
Not anymore. Today I had to create an intermediary DLL between two different object file formats and I had to go down to the level of dirty and hacky in the quest to make it work. And I stumbled upon this awesome page that has the "ultimate header file" template. I discovered half the things there myself, but it nailed the coffin of problems for me.
Here are the problems that I had to tackle in general:
- You can't have both
__declspec(dllexport)and__declspec(dllimport)in your header, that's why you can't use the same header for both compiling the library and the user of the library. - When the user of the library prefers C and your library is in C++, you are hosed because your library has a symbol like (__imp_?calculateSquare@@YAHH@Z) and the user's object file has __imp__calculateSquare. Therefore you get linker errors. C and C++ don't mix.
These are some of the things that make DLLs tick in windows. I'm really glad to have learned this so that I can understand where library developers are coming from. Let me shamelessly repeat that awesomeness from flounder.com:
#ifndef _DEFINED_uniqueheadername //---------------1---------------+
#define _DEFINED_uniqueheadername //---------------1---------------+
// |
#if _MSC_VER > 1000 //--------------2---------------+ |
#pragma once // | |
#endif //----------------------------2---------------+ |
// |
#ifdef __cplusplus //---------------3---------------+ |
extern "C" { // | |
#endif // __cplusplus //------------3---------------+ |
// |
#ifdef _COMPILING_uniqueheadername //-----------4-----------+ |
#define LIBSPEC __declspec(dllexport) // | |
#else // | |
#define LIBSPEC __declspec(dllimport) // | |
#endif // _COMPILING_uniqueheadername //--------4-----------+ |
// | |
LIBSPEC linkagetype resulttype name(parameters); // | |
// ... more declarations as needed // | |
#undef LIBSPEC //------------------------------4-----------+ |
// |
#ifdef __cplusplus //----------------5---------------+ |
} // | |
#endif // __cplusplus //---------------5---------------+ |
#endif // _DEFINED_uniqueheadername //-----------------1------------+
