Annotation of mstools/mfc/doc/tn011.txt, revision 1.1.1.1

1.1       root        1: Microsoft Foundation Classes                           Microsoft Corporation
                      2: Technical Notes
                      3: 
                      4: #11 : Using MFC as part of a DLL
                      5: 
                      6: This note describes how you can use the MFC library as part of a
                      7: Windows DLL.  This note assumes you are familiar with Windows DLLs
                      8: and how to build them.
                      9: 
                     10: =============================================================================
                     11: Overview
                     12: ========
                     13: 
                     14: We will describe how you can build a DLL that uses MFC classes.  We
                     15: provide simplified DLL support to reduce the impact on the MFC
                     16: and C++ user.
                     17: 
                     18: Interfaces:
                     19: -----------
                     20: This simplified DLL support assumes that interfaces between the application
                     21: and the DLL are specified in normal C-like functions or explicitly exported
                     22: classes.  MFC Class interfaces are not automatically exported.
                     23: 
                     24: If both a DLL and an application want to use MFC, then they will both
                     25: have a copy of the MFC library statically linked into them.  In fact,
                     26: the versions of the libraries will be different.  The application uses
                     27: one of the standard versions of the MFC library (depending on the memory
                     28: model, say 'mafxcw.lib') which the DLL uses a special version of the MFC
                     29: library ('lafxdwd.lib').
                     30: 
                     31: This gives you several advantages including:
                     32: 
                     33: * the application using the DLL does not have to use MFC, or for
                     34:     that matter it does not have to be a C++ application.
                     35: 
                     36: * the memory model of the application can be different than the DLL.  For
                     37:     example our DLLs are large model, but the application using the DLL
                     38:     can still be medium model.
                     39: 
                     40: * the size of the DLL depends only on those MFC and C runtime routines
                     41:     that are used and linked in by the linker. Therefore the size of a
                     42:     WINDLL is only slightly bigger than the exact same code in a large
                     43:     model application.
                     44: 
                     45: * there are no problems with classes changing underneath you.  DLL
                     46:     designers export only those interfaces they wish to.
                     47: 
                     48: * if both DLL and application use MFC, there are no problems with the
                     49:     application wanting a different version of MFC than the DLL (or vice
                     50:     versa).  Since the MFC library is statically linked into each DLL
                     51:     or EXE, there is no question about which version you have.
                     52: 
                     53: * Several messy technical problems are avoided by not trying to split
                     54:     classes across DLL boundaries.  The Microsoft C++ compiler does
                     55:     support this feature with the "__export" keyword on classes.  Please
                     56:     refer to the C7 language reference for more details.
                     57: 
                     58: 
                     59: Limitations:
                     60: ============
                     61: 
                     62: Some of the C runtime functions are not supported in DLLs.
                     63: As a result of this, the following MFC functionality is not available
                     64: in DLL-compatible MFC libraries:
                     65: 
                     66:         CTime::Format,
                     67:         CTime::FormatGmt,
                     68:         CTimeSpan::Format
                     69: 
                     70: The MFC classes assume large model for the WINDLL version.  As with any
                     71: DLL, we also assume "SS != DS" (SS points to the application's
                     72: stack segment, while DS points to the DLL's data segment).
                     73: 
                     74: The OLE classes are not part of the WINDLL version.  This is a practical
                     75: consideration since OLE servers tend to be small stand-alone executables
                     76: and MFC does not support OLE handlers (i.e. a more efficient way to build
                     77: an OLE server packaged in a DLL).
                     78: 
                     79: =============================================================================
                     80: What to do in your DLL code:
                     81: ============================
                     82: 
                     83: Building:
                     84: ---------
                     85: When compiling your windows DLL, the symbol "_WINDLL" must be defined.
                     86: Your DLL code must also be compiled with the following compiler switches:
                     87:     /ALw
                     88:        large model, SS!=DS
                     89:     /GD
                     90:        signifies you are a windows DLL (and causes the compiler to
                     91:        automatically define _WINDLL)
                     92: 
                     93: The interfaces between the application and the DLL must be explicitly
                     94: exported.  We recommend you define your interfaces to be low bandwidth,
                     95: sticking to C interfaces where possible.  More direct C interfaces
                     96: are easier to maintain than more complex C++ classes.
                     97: 
                     98: If you wish high bandwidth C++ classes for your DLL interfaces,
                     99: please see the C7 language reference for a description of how to export
                    100: a class.  This has a lot more subtleties to understand to use effectively.
                    101: 
                    102: We recommend you place these interfaces in a separate header that can
                    103: be included by both C and C++ files (that way you won't limit your DLL
                    104: customers to C++ programmers).  See the header 'TRACEAPI.H' in the DLLTRACE
                    105: sample program for an example.
                    106: 
                    107: Make sure these interfaces are declared as "FAR PASCAL _export"
                    108: routines.  If you want your interfaces to work for mixed model
                    109: client applications, add explicit "FAR" keywords for data pointers.
                    110: 
                    111: WinMain->LibMain
                    112: ================
                    113: The MFC library will define the standard windows 'LibMain' entry point
                    114: that will initialize your CWinApp derived object as in a normal MFC
                    115: application.  Place all DLL specific initialization in the
                    116: 'InitInstance' member function as with a normal MFC application.
                    117: 
                    118: Note: the CWinApp::Run mechanism doesn't apply to a DLL since the
                    119: application owns the main message pump.  If your DLL brings up modeless
                    120: dialogs or has a main frame window of its own, your application's main
                    121: message pump must call a DLL-exported routine that calls CWinApp's
                    122: PreTranslateMessage.
                    123: See the DLLTrace sample for use of this function.
                    124: 
                    125: WEPs
                    126: ====
                    127: If desired you can provide a Windows Exit Procedure (WEP) for your
                    128: DLL just as described in the C SDK.
                    129: 
                    130: =============================================================================
                    131: What to do to link it all together:
                    132: ===================================
                    133: 
                    134: You must do a one time build of the WINDLL version of the MFC library.
                    135: The WINDLL version of the MFC library is built with the command line:
                    136: 
                    137:     nmake MODEL=L TARGET=W DLL=1 DEBUG=1
                    138:       for the debugging version of the library 'lafxdwd.lib'
                    139:     nmake MODEL=L TARGET=W DLL=1 DEBUG=0
                    140:       for the retail version of the library 'lafxdw.lib'
                    141: 
                    142: You must link your DLL with this library (lafxdwd or lafxdw) along with
                    143: the large model WINDLL version of the C runtimes called 'ldllcew.lib'.
                    144: 
                    145: =============================================================================
                    146: Sample Code:
                    147: ============
                    148: 
                    149: Please see the MFC sample program directory DLLTRACE for a complete sample.
                    150: This includes a simple DLL called 'TRACER.DLL' that implements the
                    151: AFX Trace flags dialog (see TN007.TXT).
                    152: It also has a simple HELLO.EXE application that calls the DLL to
                    153: use the dialog.
                    154: 
                    155: Several interesting thing to note:
                    156: 
                    157: * the memory model and compiler flags of the DLL and the application
                    158:     are very different.
                    159: 
                    160: * the link lines and .DEF files for the DLL and the application are also
                    161:     very different.
                    162: 
                    163: * even though MFC DLLs must be large model, the application that uses
                    164:     them can be any memory model you like.
                    165: 
                    166: * the application using the DLL doesn't even have to be in C++.
                    167: 
                    168: * the interface between the application and the DLL is a "C"-like API
                    169:     with the compiler '_export' keyword set - see TRACEAPI.H.
                    170: 
                    171: The one API defined in TRACEAPI.H illustrates what is needed for your
                    172: APIs you will define in your DLL:
                    173: 
                    174:     #ifdef __cplusplus
                    175:     extern "C" {
                    176:     #endif  /* __cplusplus */
                    177: 
                    178:     struct TracerData
                    179:     {
                    180:         BOOL    bEnabled;
                    181:         UINT    flags;
                    182:     };
                    183: 
                    184:     BOOL FAR PASCAL __export PromptTraceFlags(TracerData FAR* lpData);
                    185: 
                    186:     #ifdef __cplusplus
                    187:     }
                    188:     #endif
                    189: 
                    190: * the declaration is enclosed in an 'extern "C" { }' block for C++ users.
                    191:     This has several advantages.  First it makes your DLL APIs usable
                    192:     by non-C++ client applications.  Second it reduces DLL overhead
                    193:     since C++ name mangling will not be applied to the exported name.
                    194:     Lastly it makes it easier to explicitly add to a .DEF file (for
                    195:     exporting by ordinal) without having to worry about name mangling.
                    196: 
                    197: * all API functions are 'FAR PASCAL __export'.
                    198:     This will generate the correct prologue/epilogue sequence for the
                    199:     DLL entry points when we use the /GD compiler switch to build the DLL.
                    200:     There is no need to do any archaic "MakeProcInstance"s or '_loadds'
                    201:     entry points.
                    202: 
                    203: * the structures used by the API are not derived from MFC classes, and
                    204:     are defined completely in the API header.  This reduces the complexity
                    205:     of the interface between the DLL and the application and once again
                    206:     makes the DLL usable by C programs as well.
                    207: 
                    208: * any data pointers used in the API are explicit FAR pointers.
                    209:     Since the DLL is compiled large model, data pointers are already
                    210:     FAR pointers by default.  Adding the extra FAR keyword will allow
                    211:     your client applications to be small or medium model without having
                    212:     to change your header.
                    213:     Never have 'NEAR' pointers in an interface for a DLL.
                    214:   
                    215: =============================================================================

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.