Short version:
Can a COM class modify its own virtual table entries at runtime? (disregarding thread issues)
Full version:
I'm providing a number of C++ classes which implement a com interface. The COM interface is defined in a third-party framework.
(Edited: The vtable of the COM interface is standard on Windows platform; but the relationship between the C++ vtable and the COM vtable isn't clear to me.)
In order to inject my implementations correctly into that framework, it needs to use two-step initialization: first create an object with no parameters, then call an Initialize method with all parameters. This is the moment when one of my implementations can be chosen.
To make this happen, I added a "resolver" class (or simply a wrapper class), whose sole responsibility is to choose an implementation in the Initialize method. After that, every call to its COM methods will be forwarded to the actual implementation.
The resolver class is then injected into the framework. This gets around the framework limitation.
Now, seeing that the resolver class doesn't really have any use after initialization, I'm wondering if there is a way to get rid of the virtual method indirection cost? My idea is to copy each COM vtable entry from the concrete implementation to the vtable of the resolver class.
Will this work?
Example:
// (FYI) #define HRESULT unsigned long
struct IInterface
{
// ... the usual AddRef, Release and QI omitted
virtual HRESULT Initialize(VARIANT v) = 0; // the Initialize method, where implementation gets chosen
virtual HRESULT DoWork() = 0; // can only call after initialization.
};
class MyResolver : public IInterface
{
// ... the usual AddRef, Release and QI omitted
public:
virtual HRESULT Initialize(VARIANT v)
{
if ( /* some conditions based on v */ )
return Implem_One.Create((void**) &m_pImpl);
else
return Implem_Two.Create((void**) &m_pImpl);
"Here, can I copy the vtable entries from m_pImpl to the vtable of MyResolver (*this) ?";
for (int k = 0; k < num_virtual_methods; ++k)
this->vtbl[k] = m_pImpl->vtbl[k];
}
virtual HRESULT DoWork()
{
if (!m_pImpl) return ERROR_NOT_INITIALIZED;
m_pImpl->DoWork();
}
public:
// this creation method is injected into the framework
static HRESULT Create(void**) { /* create an instance of this class and return it */ }
private:
MyResolver() : m_pImpl(NULL) {}
virtual ~MyResolver() { if (m_pImpl) m_pImpl->Release(); }
IInterface* m_pImpl;
};
virutal long. Thanks for suggestion. - rwong