Exporting By Ordinal From an Extension DLLID: Q120263
|
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.
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.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.
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.
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.
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"
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.
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.Additional query words: kbinf 1.00 1.50 2.00 2.50 C2737
Keywords : kb16bitonly kbDLL kbMFC kbVC
Version : 1.00 1.50
Platform : WINDOWS
Issue type :
Last Reviewed: August 5, 1999