How do you make a class accessible from a dynamic link library? It is a commonly asked question with a solution that is surprisingly simple. In this article I will show you how to do it in Visual C++.
First, you need to create a new project using the Win32 Dynamic-Link Library project wizard.
Then, create a new class. Call it CInDLL. We now have a class with a constructor and a destructor.
We want to access this class from the DLL, so we need to export it. When the DLL is built, it also builds something called an export library. The export library is similar to a regular library. It contains all of the information necessary to dynamically link to the DLL at runtime. When we export a function or a class, the function name and location is stored in the export library. The program using the DLL links in the export library to access the DLL.
There are two ways to export a function or class from a DLL. One is to use the __declspec(dllexport) directive. The other is to use definition files. The former is easier and we will be covering it first.
Change the class definition to look like the following:
class __declspec(dllexport) CInDLL
Compile the DLL. Everything should work correctly. If you look in your destination directory you should see the DLL and export library for this project. Congratulations, you have just created your first DLL!
We now need to use the DLL.
Create a new Win32 Console Application in the same directory and workspace. Call it TestClassInDLL. Be sure and make it dependent on ClassInDLL. Watch the directory. Put it in the same directory as the DLL - not below it. Open the project settings. Be sure you are editing the Debug build settings. Add Debug\ClassInDLL.lib to the list of Object/Libaray Modules under the link tab. Add a corresponding file for the release build.
Create and add a file called TestClassInDLL.cpp with the following code:
int main()
{
return 0;
}
The program should compile although it obviously doesn't do much. We need to import the class from our DLL into the program. We are currrently not set up to do that. Where the DLL had to export the class, the application must import it by adding the expression __declspec(dllexport) in the class definition. We want to modify the header file to serve both purposes.
Go back to the DLL project and add a file called ClassInDLL.h with the following source:
#ifndef ClassInDLL_H
#define ClassInDLL_H
#ifdef _CLASSINDLL
#define CLASSINDLL_CLASS_DECL __declspec(dllexport)
#else
#define CLASSINDLL_CLASS_DECL __declspec(dllimport)
#endif
#endif // ClassInDLL_H
This creates a macro that, depending on a #define, switches between importing and exporting. Add the _CLASSINDLL preprocessor to your DLL project settings under C/C++-Preprocessor. Include ClassInDLL.h in InDLL.H and change the CInDLL declaration to the following:
class CLASSINDLL_CLASS_DECL CInDLL
Include InDLL.h in TestClassInDLL.cpp. The DLL defines _CLASSINDLL so that CLASSINDLL_CLASS_DECL becomes an export instruction. The application does not; therefore, CLASSINDLL_CLASS_DECL becomes an import instruction by default. CInDLL is now accessible from your application. Create an instance of it in your main function:
int main()
{
CInDLL classFromDLL;
return 0;
}
Rebuild everything and run the program. Be sure you rebuild the DLL first!
You can see that it doesn't do much. Let's add a function to CInDLL. You don't need to do anything special. Just add the method prototype in the header, the function body in the cpp file, and any necessary include files:
void CInDLL::TestIt()
{
cout << "Hello World from a DLL." << endl;
}
Call Testit() from your application. Compile and run the DLL and application. Congratulations, you have just put a class in a DLL.