What you describe is a Regular DLL Dynamically Linked to MFC. Selecting part of the description from this linked article gives you a sub-set of the characteristics:
A regular DLL, dynamically linked to MFC has the following
requirements:
These DLLs are compiled with _AFXDLL defined, just like an executable that is dynamically linked to the MFC DLL. But _USRDLL is
also defined, just like a regular DLL that is statically linked to
MFC.
This type of DLL must instantiate a CWinApp-derived class.
This type of DLL uses the DllMain provided by MFC. Place all DLL-specific initialization code in the InitInstance member function
and termination code in ExitInstance as in a normal MFC application.
If you use the New Project Wizatd from VS2010 and choose the option to create an MFC DLL, this is the default you get, although you can select other types of DLL from the wizard options:
So, create a regular DLL. It will generate the necessary boilerplate code for you, including a CWinApp
derived class. For example:
// CMFCLibrary1App
BEGIN_MESSAGE_MAP(CMFCLibrary1App, CWinApp)
END_MESSAGE_MAP()
// CMFCLibrary1App construction
CMFCLibrary1App::CMFCLibrary1App()
{
// TODO: add construction code here,
// Place all significant initialization in InitInstance
}
// The one and only CMFCLibrary1App object
CMFCLibrary1App theApp;
// CMFCLibrary1App initialization
BOOL CMFCLibrary1App::InitInstance()
{
CWinApp::InitInstance();
return TRUE;
}
I suggest you create such a project and then port your existing code into it, then you will have all of the correct project settings and structure from the start. This is much easier than trying to convert e.g. an exe project to a dll project.
Be sure to note the differences in the way you must write your exported functions. As the link above says:
Because this kind of DLL uses the dynamic-link library version of MFC,
you must explicitly set the current module state to the one for the
DLL. To do this, use the AFX_MANAGE_STATE
macro at the beginning of
every function exported from the DLL.
So even if you only export C-style functions, if they wrap objects that use MFC, then the exported functions and any public functions of exported classes must use the above technique, particularly for multi-threaded applications.
The New Project template helpfully inserts comments explaining this too:
//TODO: If this DLL is dynamically linked against the MFC DLLs,
// any functions exported from this DLL which call into
// MFC must have the AFX_MANAGE_STATE macro added at the
// very beginning of the function.
//
// For example:
//
// extern "C" BOOL PASCAL EXPORT ExportedFunction()
// {
// AFX_MANAGE_STATE(AfxGetStaticModuleState());
// // normal function body here
// }
//
// It is very important that this macro appear in each
// function, prior to any calls into MFC. This means that
// it must appear as the first statement within the
// function, even before any object variable declarations
// as their constructors may generate calls into the MFC
// DLL.
//
// Please see MFC Technical Notes 33 and 58 for additional
// details.
//
The Technical Notes referred to in the above comments are:
Seeing that you use LoadLibrary
to dynamically load your DLL, if you are doing this from an MFC application, you would be wise to use AfxLoadLibrary
instead (and the corresponding AfxFreeLibrary
). As MSDN says:
For MFC applications that load extension DLLs, we recommend that you
use AfxLoadLibrary instead of LoadLibrary. AfxLoadLibrary handles
thread synchronization before you call LoadLibrary. The interface
(function prototype) to AfxLoadLibrary is the same as LoadLibrary.
The documentation for AfxLoadLibrary
has more details.