MFC Extension dll VS Regular Dll

1. Dll types
Three:
Win32 dll
MFC regular dll
MFC extension dll
2. MFC extension dll
Basic[MSDN]:
An MFC extension DLL is a DLL that typically implements reusable classes derived from the existing Microsoft Foundation Class Library classes.

An MFC extension DLL has the following features and requirements:

    *      The client executable must be an MFC application compiled with _AFXDLL defined.
    *      An extension DLL can also be used by a regular DLL that is dynamically linked to MFC.
    *      Extension DLLs should be compiled with _AFXEXT defined. This forces _AFXDLL to be also defined and ensures that the proper declarations is pulled in from the MFC header files. It also ensures that AFX_EXT_CLASS is defined as __declspec(dllexport) while building the DLL, which is necessary if you are using this macro to declare the classes in your extension DLL.
    *      Extension DLLs should not instantiate a class derived from CWinApp, but should rely on the client application (or DLL) to provide this object. [my note: since every CWinApp needs to manage its module state, as extension dll just use the caller's, so it just accepts the current module state.]
    *      Extension DLLs should, however, provide a DllMain function and do any necessary initialization there.

An MFC extension DLL uses a shared version of MFC in the same way an application uses the shared DLL version of MFC, with a few additional considerations:

    *      It does not have a CWinApp-derived object. It must work with the CWinApp-derived object of the client application. This means that the client application owns the main message pump, the idle loop, and so on.
    *      It calls AfxInitExtensionModule in its DllMain function. The return value of this function should be checked. If a zero value is returned from AfxInitExtensionModule, return 0 from your DllMain function.
    *      It creates a CDynLinkLibrary object during initialization if the extension DLL wants to export CRuntimeClass objects or resources to the application.

Memory Management

MFCx0.dll and all extension DLLs loaded into a client application's address space use the same memory allocator, resource loading, and other MFC global states as if they were in the same application. This is significant because the non-MFC DLL libraries and the regular DLLs do the exact opposite and have each DLL allocating out of its own memory pool.

Sharing Resources and Classes

Exporting resources is done through a resource list. Each application contains a singly linked list of CDynLinkLibrary objects. When looking for a resource, most of the standard MFC implementations that load resources look first at the current resource module (AfxGetResourceHandle) and if the resource is not found walk the list of CDynLinkLibrary objects attempting to load the requested resource.

Walking the list has the disadvantages that it is slightly slower and requires managing resource ID ranges. It has the advantage that a client application that links to several extension DLLs can use any DLL-provided resource without having to specify the DLL instance handle. AfxFindResourceHandle is an API used for walking the resource list to look for a given match. It takes the name and type of a resource and returns the resource handle where it was first found (or NULL).

If you do not want to walk the list and only load resources from a specific place, use the functions AfxGetResourceHandle and AfxSetResourceHandle to save the old handle and set the new handle. Be sure to restore the old resource handle before you return to the client application. For an example of using this approach to explicitly load a menu, see Testdll2 .cpp in the MFC sample DLLHUSK.

3. MFC regular dll (Talk only Regular DLLs Dynamically Linked to MFC)

Basic [MSDN]:

A regular DLL dynamically linked to MFC is a DLL that uses MFC internally, and the exported functions in the DLL can be called by either MFC or non-MFC executables. As the name describes, this kind of DLL is built using the dynamic-link library version of MFC (also known as the shared version of MFC). Functions are usually exported from a regular DLL using the standard C interface.

You must add the AFX_MANAGE_STATE macro at the beginning of all the exported functions in regular DLLs that dynamically link to MFC to set the current module state to the one for the DLL. This is done by adding the following line of code to the beginning of functions exported from the DLL:

AFX_MANAGE_STATE(AfxGetStaticModuleState( ))

A regular DLL, dynamically linked to MFC has the following features:

    *      This is a new type of DLL introduced by Visual C++ 4.0.
    *      The client executable can be written in any language that supports the use of DLLs (C, C++, Pascal, Visual Basic, and so on); it does not have to be an MFC application.
    *      Unlike the statically linked regular DLL, this type of DLL is dynamically linked to the MFC DLL (also known as the shared MFC DLL).
    *      The MFC import library linked to this type of DLL is the same one used for extension DLLs or applications using the MFC DLL: MFCxx(D).lib.

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.

All memory allocations within a regular DLL should stay within the DLL; the DLL should not pass to or receive from the calling executable any of the following:

    *      pointers to MFC objects
    *      pointers to memory allocated by MFC

If you need to do any of the above, or if you need to pass MFC-derived objects between the calling executable and the DLL, then you must build an extension DLL.

Key points:
1) it has its own module state. So regards to resource loading (string, dialog, etc), in order to load its resource correctly, module state switch before loading resource is a must.
2) for every exported function from this dll, the switching module state sentence must be the first code line of every function.
3) The AFX_MANAGE_STATE macro should not be used in regular DLLs that statically link to MFC or in extension DLLs.

4. Loading resource example (from codeguru)

The article link is:http://www.codeguru.com/cpp/w-p/dll/article.php/c109

[Key extraction]The next issue involving DLLs and dialog boxes, involves a DLL invoking a dialog which is located in a different DLL. There are four calling possibilities: 1. Regular calling and Regular DLL, 2. An Extension calling and Regular DLL, 3. A Regular calling an Extension DLL, 4. Extension calling a Extension DLL.
case 1: since it's hard to directly use the exported dialog class as module state can't be switched to the parent regular dll's of the wanted dialog, the dialog resource can't be located, the only way to be able to call the dialog is by exporting a function which inside it can show the dialog.
case 2: same as #1.
case 3: as the regular dll has its module state and the extension dll has no way to join in its resource chain and no way to do module state switch as it can only accept the caller's module state, so no way to realize the dialog call here.
case 4: easy. any way can be fine.

5. Other

1) No need to worry about the project setting's preprocessors and CRT setting. New a MFC extension or regular dll in VS, you will get standard setting there.

2) MFC Module state. Only regular dll needs to manage module state, while for MFC extension dll, it will only accept a module state as it may be called by regular dll or MFC application directly (exe), but it really has no way to do sth with module state.

原文地址:https://www.cnblogs.com/taoxu0903/p/1453718.html