Exporting classes...
Jean FEVRE -- jeanf@afp.com Tuesday, February 06, 1996 We wrote some classes that we use very often and put them in some DLL. What is the best way to export class members with allways the same ID. I try two DEF manager : dllxport32 and defmgr32. What is the best solution from msvc 4.0. What is used by Microsoft for the generation of MFC40.DLL??? regards Jean
Brian V. Zaino 516 233-6862 -- brian.zaino@reuters.com Thursday, February 08, 1996 [Mini-digest: 3 responses] >>We wrote some classes that we use very often and put them in=20 >>some DLL. >>What is the best way to export class members with allways the=20 >>same ID. I try two DEF manager : dllxport32 and defmgr32. >> >>What is the best solution from msvc 4.0. >> >>What is used by Microsoft for the generation of MFC40.DLL??? >> >>regards >> >>Jean Jean, Below, I have included one suggestion for exposing a=20 C++ class from a dll. Brian V. Zaino Internet: brian.zaino@reuters.com A method for exposing a C++ class from a dll. This method consists of: 1. A class factory which can instantiate the objects. 2. An Interface definition which is given to the user of the dll. 3. A proxy class which implements the Interface and is instantiated by the class factory. 4. A real class which does the actual work. The appropriate members are called via the proxy class. The user of the dll never sees this real class. Some Problems: 1. Additional Indirection. 2. Additional work for the class writer. Instead of just having to implement the real class, the proxy class needs to be implemented as well. Some Benefits: 1. You can add functionality to the real class without affecting the interface. For example, you can add a new member function X to the real class without changing the proxy or interface classes. In this case, you would probably keep the original interface and proxy for backwards compatibility and then add a new interface that has full functionality. 2. You can support more than one interface at the same time. There is no reason why the real class can be acted upon by several interfaces and proxy classes. Sample code follows: 1. Here are some defines for the exported classes and functions.=20 BUILD_DLL is defined by the DLL=92s environment and NOT by the user o= f the DLL. This #define should be different for each dll. The purpose of these #defines is to allow sharing of headers between the DLL and the users of the DLL. #ifdef BUILD_DLL #define MYDllExport __declspec(dllexport) #else #define MYDllExport #endif 2. Define a pure virtual interface class without constructor and destructor. This is the interface you want the user of the DLL to see. In fact, this definition should be placed into a *.h file that will be given to the user of the DLL. Note that this class has no implementation. It is just an interface. class MYDllExport IInterface { public: virtual BOOL SomeFunctionA(int nA)=3D0; virtual BOOL SomeFunctionB(Cstring csB)=3D0; virtual BOOL SomeFunctionY(int nA, int nY)=3D0; }; 3. Define and implement the real/worker class. This class can anything you need it to be. It is possible to have one class with several interfaces. class CRealClass { // Friend classes are any classes that proxy for us. friend class CInterfaceProxy; private: // private constructor/destructor so that only the friend classes can // create an instance of this class. CRealClass(); ~CRealClass(); public: virtual BOOL RealFunctionA(int nA); virtual BOOL RealFunctionB(Cstring csB); virtual BOOL RealFunctionNewY(int nA, int nY); }; CRealClass::CRealClass() { } CRealClass::~CRealClass() { } BOOL CRealClass::RealFunctionA(int nA) { // Perform work here. return(TRUE); } BOOL CRealClass::RealFunctionB(Cstring csB) { // Perform work here. return(TRUE); } BOOL CRealClass::RealFunctionNewY(int nA, int nY) { // Perform work here. return(TRUE); } 4. Define and Implement the Interface Proxy Class. This class is th= e implementation of the exported interface (Iinterface) class. class CInterfaceProxy : public IInterface { // Friend classes are my class factory. friend IInterface* CreateInterface(); private: // constructor/destructor are private so only the class factory ca= n // instantiate one. CInterfaceProxy(); ~CInterfaceProxy(); public: virtual BOOL SomeFunctionA(int nA); virtual BOOL SomeFunctionB(Cstring csB); virtual BOOL SomeFunctionY(int nA, int nY); private: // Class has pointer to the real class. CRealClass * m_pRealClass; }; CInterfaceProxy:: CInterfaceProxy() { m_pRealClass =3D new CRealClass; } CCommPortProxy::~CCommPortProxy() { delete m_pRealClass; } BOOL CInterfaceProxy::SomeFunctionA(int nA) { return(m_pRealClass->RealFunctionA(nA)); } BOOL CInterfaceProxy::SomeFunctionB(Cstring csB) { return(m_pRealClass->RealFunctionB(csB)); } BOOL CInterfaceProxy::SomeFunctionY(int nA, int nY) { return(m_pRealClass->RealFunctionNewY(nA, nY)); } 5. Define and implement the "ClassFactory" that is used to obtain a copy of the Interface. This is very similar to the OLE mechanism of Query Interface. This is the only interface that is really exported =66rom the DLL. MYDllExport IInterface* CreateInterface(); MYDllExport IInterface* CreateInterface() { CInterfaceProxy* pInterface; pInterface =3D new CInterfaceProxy(); // Error and Exception handling code should be entered here. // If everything is OK, return the Pointer to the Proxy Class. return(pInterfaceProxy); } -----From: "Paul Fonte - Ext. 4633"dllxpt32 should maintain the ordinal values for you if you use the /r (for reference file) option and specifiy the output filename (it will overwrite the file, maintaining ordinal placement) -----From: "Mike Blaszczak" From: owner-mfc-l@netcom.com on behalf of Jean FEVRE > We wrote some classes that we use very often and put them in > some DLL. What is the best way to export class members with allways the > same ID. I try two DEF manager : dllxport32 and defmgr32. I don't know what you mean by "DEF manager". > What is the best solution from msvc 4.0. Generally, it is using the AFX_CLASS_EXP macro and all of its friends. > What is used by Microsoft for the generation of MFC40.DLL??? An amazingly impressive batch file which takes the MAP file generated by the linker, chews it up, formats it, sorts it, and then links again with that DEF file. It works using Unix tools like grep and a couple of dodads that just read files, add numbers, and spit 'em out again. It's fun to watch, but it is certainly nothing I would like to ship. .B ekiM TCHAR szMSDisc[] = _T("I don't speak for Microsoft");
Mukesh Prasad Development Contractor -- mukesh@everest.XAIT.Xerox.COM Monday, February 12, 1996 >We wrote some classes that we use very often and put them in=20 >some DLL. >What is the best way to export class members with allways the=20 >same ID. I try two DEF manager : dllxport32 and defmgr32. > >What is the best solution from msvc 4.0. > I think you are asking how to keep "ordinal numbers"s the same from release to release. If so, here is one scheme we have used: 1) Make the DLL. 2) Run "dumpbin /exports" on the DLL (or "exehdr"), redirecting the output to a text file. 3) Write a small program to _parse_ the text file from (2), separate out the mangled names, and write them out to a third file. The output is your ".def" file, so assign ordinal numbers. 4) From now on, always use this ".def" file in making the DLL. Step 3 is much easier if you have access to a Unix system with its text processing tools. This is the general idea, though you will still have to handle changes. Some ordinals will get deleted and some added. It is a good idea never to re-use ordinals, but just keep adding new ones at the end.
| Вернуться в корень Архива |