home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgLangD.iso / C++-7 / DISK11 / MFC / DOC / TN011.TX$ / tn011
Encoding:
Text File  |  1992-03-18  |  8.6 KB  |  216 lines

  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. =============================================================================
  216.