The Microsoft Windows equivalent to the Linux / Unix shared object (".so") is the ".dll". The Microsoft Windows DLL file usually has the extension ".dll", but may also use the extension ".ocx". On the old 16 bit windows, the dynamically linked libraries were also named with the ".exe" suffix. "Executing" the DLL will load it into memory.
The Visual C++ .NET IDE wizard will create a DLL framework through the GUI, and generates a ".def" file. This "module definition file" lists the functions to be exported. When exporting C++ functions, the C++ mangled names are used. Using the Visual C++ compiler to generate a ".map" file will allow you to discover the C++ mangled name to use in the ".def" file. The "SECTIONS" label in the ".def" file will define the portions which are "shared". Unfortunately the generation of DLLs are tightly coupled to the Microsoft IDE, so much so that I would not recomend trying to create one without it.
The Microsoft Windows C++ equivalent functions to libdl are the following functions:
- ::LoadLibrary() - dlopen()
- ::GetProcAddress() - dlsym()
- ::FreeLibrary() - dlclose()
[Potential Pitfall]: Microsoft Visual C++ .NET compilers do not allow the linking controll that the GNU linker "ld" allows (i.e. --whole-archive, -no-whole-archive). All symbols need to be resolved by the VC++ compiler for both the loadable library and the application executable individually and thus it can cause duplication of libraries when the library is loaded. This is especially bad when using static variables (i.e. used in singleton patterns) as you will get two memory locations for the static variable, one used by the loadable library and the other used by the program executable. This breaks the whole static variable concept and the singleton pattern. Thus you can not use a static variable which is referenced by by both the loadable library and the application executable as they will be unique and different. To use a unique static variable, you must pass a pointer to that static variable to the other module so that each module (main executable and DLL library) can use the same instatiation. On MS/Windows you can use shared memory or a memory mapped file so that the main executable and DLL library can share a pointer to an address they both will use.
Cross platform (Linux and MS/Windows) C++ code snippet:Include file declaration: (.h or .hpp)
class Abc{
public:
static Abc* Instance(); // Function declaration. Could also be used as a public class member function.
private:
static Abc *mInstance; // Singleton. Use this declaration in C++ class member variable declaration.
...
}
|
C/C++ Function source: (.cpp)
/// Singleton instantiation
Abc* Abc::mInstance = 0; // Use this declaration for C++ class member variable
// (Defined outside of class definition in ".cpp" file)
// Return unique pointer to instance of Abc or create it if it does not exist.
// (Unique to both exe and dll)
static Abc* Abc::Instance() // Singleton
{
#ifdef WIN32
// If pointer to instance of Abc exists (true) then return instance pointer else look for
// instance pointer in memory mapped pointer. If the instance pointer does not exist in
// memory mapped pointer, return a newly created pointer to an instance of Abc.
return mInstance ?
mInstance : (mInstance = (Abc*) MemoryMappedPointers::getPointer("Abc")) ?
mInstance : (mInstance = (Abc*) MemoryMappedPointers::createEntry("Abc",(void*)new Abc));
#else
// If pointer to instance of Abc exists (true) then return instance pointer
// else return a newly created pointer to an instance of Abc.
return mInstance ? mInstance : (mInstance = new Abc);
#endif
}
|
Windows linker will pull two instances of object, one in exe and one in loadable module. Specify one for both to use by using memory mapped pointer so both exe and loadable library point to same variable or object.
Note that the GNU linker does not have this problem.For more on singletons see the YoLinux.com C++ singleton software design pattern tutorial.