Microsoft KB Archive/120263

{|
 * width="100%"|

Exporting By Ordinal From an Extension DLL

 * }

Q120263

-

The information in this article applies to:


 * The Microsoft Foundation Classes (MFC), included with:
 * Microsoft Visual C++, versions 1.0, 1.5

-

SUMMARY
When building Microsoft Foundation Class extension DLLs -- DLL's built with _AFXDLL using the MFC200(D).DLL or MFC250(D).DLL or _USRDLL DLLs but not built using the MFC2xx(D).DLL -- you may want to export functions only by ordinal. This will reduce the amount of time necessary to look up the function in the DLL's export table, and it will also reduce the size of the DLL because the DLL will not need to store the names of the functions, which is necessary when you export functions by name.

To do this, exported functions, classes, or member functions must have their full decorated names listed in the EXPORTS section of the DLL's .DEF file with the ordinal you have given them and the NONAME keyword.

Determining the correct decorated names necessary for such exporting can be difficult. This article describes a general technique for using a mapfile generated by linking with the /MAP:FULL linker switch to determine the decorated names to export.

MORE INFORMATION
The Microsoft Foundation Classes Technote 33: "DLL Version of MFC" describes exporting functions and classes from an MFC extension DLL. Under the section titled "Exporting Entries" it states:

Since we are exporting selective exports from our DLL (that is, not everything), we must decide which particular interfaces we wish to export. This is difficult as you must specify the mangled names to the linker in the form of entries in the .DEF file.

Don't export any C++ classes unless you really need to have a symbolic link for it. The DLLHUSK sample's TESTDLL1 has a minimal exported interface, the rest of the communication between client program and DLL is done through C++ virtual function calls and other run-time binding options like CRuntimeClass object creation.

The DLLHUSK sample's TESTDLL2 has a more complicated example of exporting a class interface that a client application can derive from. The number of entries in the export list can grow very quickly using this approach. Depending on what particular MFC features you wish to export, you may or may not need to export all of the members of your class. You should experiment to find the smallest set of exports that still permits client applications to use the features you desire without getting link errors.

If you have tried exporting C++ classes with a .DEF file before, you will no doubt have some form of tool to generate your export list for you. The export list for MFC200[D].DLL, several thousand in number, was generated with such a process. NOTE: there is no specific tool currently available for extracting decorated names for exporting classes. Such tools are usually relatively specialized and if this is something you will need, it may be simplest to design your own. Techniques for exporting entire classes will be discussed later.

Exporting a "C" Interface
It is simplest to export functions from an extension DLL if they are marked as extern "C" as follows:

  extern "C" UINT FAR PASCAL Funct(UINT n); In such a case, all you need to do is add the name FUNCT to the EXPORT section of the DLL's .DEF file. If the function was not marked as type PASCAL (if it was a cdecl function), then the decorated name added to the EXPORTS section would be _Funct.

Functions marked as extern "C" can still access C++ objects. For more information on extern "C" see the C++ Language Reference or search on "extern" in the on-line help.

Exporting C++ Functions
To export an actual C++ function which is not a member of a class from an extension DLL, you will need to determine its decorated name. To do so, link the DLL with the /MAP:FULL switch to produce a PROJNAME.MAP file. This switch can be added if using the Visual Workbench by choosing Options, Project, Linker, Miscellaneous, and adding the switch to the "Other Options" section.

For example, if the C++ function you wish to export is:

  BOOL ValidateData( UINT nIndex, BOOL bUnique ); and a mapfile is generated using /MAP:FULL, it will have a section titled:

  Address         Publics by Name followed by a list of functions including the following text:

  0003:000E       ?ValidateData@@ZAHIH@Z int __far __cdecl ValidateData(unsigned int,int) Thus, the name you need to include in the EXPORTS section of your .DEF file is "?ValidateData@@ZAHIH@Z"

Exporting C++ Member Functions and Entire Classes
Similar examination of a generated mapfile can be used to export single member functions of a class. This technique may be useful if you only need to export certain members of a class. As Technote 33 describes above, exporting only some members of a class is preferable to exporting entire classes.

If you do need to export entire classes, in such a manner that they can be derived from, you will again need to work with the mapfile generated with /MAP:FULL.

Getting the decorated names you need to export is not all that difficult, especially with a GREP utility (a utility to search files for lines matching specific strings or patterns). Such utilities are available as freeware or shareware on many bulletin boards and electronic services.

As described earlier, linking your application with /MAP:FULL will result in a mapfile with at least one section with the headers:

  Address         Publics by Name followed by text similar to this:

  0001:10FA  ??1CDatDoc@@VEC@XZ public: virtual __far __pascal CDatDoc::~CDatDoc(void)__far   0000:0000  Imp  ??1CDocument@@VEC@XZ public: virtual __far __pascal CDocument::~CDocument(void)__far (MFC200D.168)   0001:0DD0       ??1CDView@@NEC@XZ protected: virtual __far __pascal CDView::~CDView(void)__far If you are exporting entire classes from your extension DLL, all you really need to be able to do is scan through this mapfile and pull out the decorated names belonging to your different classes. For this, a simple GREP and a stripping algorithm should suffice. In fact, you may be able to do this with a simple script if you have a powerful enough GREP utility.

In a basic case, all you might do is to grep the file for lines containing the name of the class you wish to export. Your output would be a file with all these lines. For example, if you wanted to export your CDView class, the output would probably look something like this:

0001:13BC      ??_7CDView@@6F@^J     const __far CDView::`vftable'^J 0001:0D80      ??0CDView@@JEC@XZ^J       // line break added protected: __far __pascal CDView::CDView(void)__far^J 0001:0DD0      ??1CDView@@NEC@XZ^J       // line break added protected: virtual __far __pascal CDView::~CDView(void)__far^J ... NOTE: Such output depends on the exact GREP utility used. You can then use either a fancy GREP, an editor, or some form of script file to, for each line, erase everything up to the first '?', and from the '^J' onward. (The ^J should be dropped.) There are many different stripping algorithms you could use.

This will leave you with the list of decorated names you need to export. Unfortunately, due to the form of the mapfile, each symbol will be listed exactly twice, so you will need to remove duplicate symbols. Again, a sophisticated GREP utility might do this for you.

Once you have such a system set up, it should be relatively easy to automate it to run through a text file containing a list of the classes you will be exporting. You might modify such a system to search for function names as well as classes, but this would take a bit more work. Note that different versions of the compiler could very possibly create different decorated names for the same function. So you will need to re-create your DEF file when you re-compile with a different version of the compiler.

Additional query words: kbinf 1.00 1.50 2.00 2.50 C2737

Keywords : kb16bitonly kbDLL kbMFC kbVC

Issue type :

Technology : kbAudDeveloper kbMFC