Re: exporting classes in a DLL using the PIMPL idiom
"2b|!2b==?" wrote:
[...]
If I have a module (builds into a DLL - moduleA.dll), that has
the following classes,
Fred, Barney, Alice
how may I use the PiMPL idiom to 'export' these classes so that
they may be used in another module (moduleB) by simply including
the header files Fred.h, Barney.h and Alice.h and linking to
moduleA.lib ?
First of all, I suggest you to read several first chapters of
"Inside COM" by Dale Rogerson. Because Pimpl idiom is the basis
for COM interfaces using across modules. D.Rogerson starts in his
book from simple C++ classes across modules, then gradually
develop COM mechanics on top of it. Also, read more about Pimpl
idiom here:
"Compilation Firewalls"
http://www.gotw.ca/gotw/024.htm
Basically what you need is three things:
1. Abstract interface class (a class with all pure virtual
methods).
2. Worker class, which actually implements the functionality.
3. One or more C functions, which constitute a factory for
classes.
For example:
// Person.h
struct Person
{
virtual ~Person() {}
virtual void Release() = 0;
};
// Fred.h
class Fred : public Person
{
public:
virtual void Release() = 0;
virtual int Foo(int param) = 0;
};
// Fred.cpp
class FredImpl : public Fred
{
public:
virtual ~FredImpl() { ... }
virtual void Release() { delete this; }
virtual int Foo(int param) { ... }
};
// moduleA.h
__declspec(dllexport/dllimport)
Person* GetPerson(LPCTSTR pszName);
// moduleA.cpp
Person* GetPerson(LPCTSTR pszName)
{
if(_tcscmp(pszName, _T("Fred"))
return new FredImpl();
if(_tcscmp(pszName, _T("Barney"))
return new BarneyImpl();
...
return NULL;
}
// ModuleB.cpp
Person* p = GetPerson(_T("Fred"));
if(!p)
// handle error
Fred* pFred = static_cast<Fred*>(p);
pFred->Foo(42);
....
pFred->Release();
That's about all. You can make template smart pointer for `Person'
descendants, which will call `Fred::Release' method in its
destructor to ensure proper resource management.
HTH
Alex