The information in this article applies to:
SUMMARYThis article supplements MFC TechNote #33. It contains some duplicate information, some corrections, and provides supplemental information to assist you in exporting classes or class members from an extension DLL. MORE INFORMATIONBuilding an Extension DLLYou can use AppWizard to create an MFC Extension DLL project, and it will automatically generate the appropriate compiler and linker settings. For more details, please see the AppWizard entry in the MFC Encyclopedia, which can be found in Books Online and in the printed documentation.If you are converting an existing project to an MFC Extension DLL, start with the standard rules for building an application using the _AFXDLL version of MFC. Then follow these steps:
Changing Your Header FilesThe goal of an extension DLL is usually to export some common functionality to one or more applications that can use that functionality. This boils down to exporting classes and global functions, which are available for your client applications.To do this, you must ensure that each of the member functions is marked as import or export as appropriate. This requires special declarations: _declspec(dllexport) and _declspec(dllimport). When your classes are used by the client applications, you want them to be declared as _declspec(dllimport). When the extension DLL itself is being built, they should be declared as _declspec(dllexport). In addition, the functions must be actually exported, so that the client programs bind to them at load time. To export your entire class, use AFX_EXT_CLASS in the class definition. This macro is defined by the framework as _declspec(dllexport) when both _AFXDLL and _AFXEXT are defined, but as _declspec(dllimport) when _AFXEXT is not defined. _AFXEXT as described above, is only defined when building your extension DLL. For example:
This example exports an entire class.
Not Exporting the Entire ClassSometimes you may want to export just the individual necessary members of your class. MFC TechNote #33 discusses some reasons for this in the section titled "Ordinals and class _export and DLL naming." For example, if you are exporting a CDialog-derived class, you might only need to export the constructor and the DoModal call. You can export these members using the DLL's .DEF file, but you can also use AFX_EXT_CLASS in much the same way on the individual members you need to export.For example:
When you do this, you may run into an additional problem due to the fact
that you are no longer exporting all members of the class. The problem is
in the way that MFC macros work. Several of MFC's helper macros actually
declare or define data members. Therefore, these data members will also
need to be exported from your DLL.
For example, the DECLARE_DYNAMIC macro is defined as follows when building an extension DLL:
The line that begins "static AFX_DATA" is declaring a static object inside
of your class. To export this class correctly and access the run-time
information from a client .EXE, you need to export this static object.
Because the static object is declared with the modifier AFX_DATA, you only
need to define AFX_DATA to be _declspec(dllexport) when building your DLL
and define it as _declspec(dllimport) when building your client executable.
As discussed above, AFX_EXT_CLASS is already defined in this way. So you
just need to re-define AFX_DATA to be the same as AFX_EXT_CLASS around your
class definition.
For example:
MFC always uses the AFX_DATA symbol on data items it defines within its
macros, so this technique will work for all such scenarios. For example it
will work for DECLARE_MESSAGE_MAP.
NOTE: if you are exporting the entire class rather than selected members of the class, static data members are automatically exported. Limitations of _AFXEXTYou can use the _AFXEXT pre-processor symbol for your extension DLLs as long as you do not have multiple layers of extension DLLs. If you have extension DLLs that call or derive from classes in your own extension DLLs, which then derive from the MFC classes, you must use your own preprocessor symbol to avoid ambiguity and linker errors such as the following:The problem is that in Win32, you must explicitly declare any data as _declspec(dllexport) if it is to be exported from a DLL, and declare any data as _declspec(dllimport) if it is to be imported from a DLL. When you define _AFXEXT, the MFC headers make sure that AFX_EXT_CLASS is defined correctly. When you have multiple layers, one symbol such as AFX_EXT_CLASS is not sufficient because an extension DLL may be exporting new classes as well as importing other classes from another extension DLL. To deal with this problem, use a special pre-processor symbol that indicates you are building the DLL itself versus just using the DLL. For example, imagine two extension DLLs (A.DLL and B.DLL). They each export some classes in A.H and B.H, respectively. B.DLL uses the classes from A.DLL. The header files would look something like this:
When A.DLL is built, it is built with /D A_IMPL, and when B.DLL is built,
it is built with /D B_IMPL. By using separate symbols for each DLL, you
ensure that CExampleB is exported and CExampleA is imported when building
B.DLL. CExampleA is exported when building A.DLL and imported when used by
B.DLL or some other client. This type of layering cannot be done when using
the built-in AFX_EXT_CLASS and _AFXEXT pre-processor symbols. The technique
described above solves this problem in a manner not unlike the mechanism
MFC itself uses when building its OLE, Database, and Network extension
DLLs.
Not Exporting the Entire ClassAgain you will have to take special care when you are not exporting an entire class. You have to ensure that the necessary data items created by the MFC macros are exported correctly. This can be done by re-defining AFX_DATA to your specific class' macro. This should be done any time you are not exporting the entire class.For example:
REFERENCES
MFC TechNote #33.
Additional query words: kbinf 2.00 2.10 3.00 3.10 4.00
Keywords : kbDLL kbMFC kbVC |
Last Reviewed: June 30, 1999 © 2000 Microsoft Corporation. All rights reserved. Terms of Use. |