Annotation of mstools/mfc/doc/tn011.txt, revision 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.