Вот что происходит в одной реализации, с которой я знаком. Не уверен, насколько универсален этот макет, но он может дать вам представление о том, что возможно.
Компоновка класса в памяти, в 32-битном режиме, выглядит следующим образом:
[ (4 bytes) ptr to vtable for IUnknown ]
[ (4 bytes) ptr to vtable for IDispatch ]
[ (4 bytes) ptr to vtable for IMyInterface ] <--- pInterface points to here
[ (....) member variables of the class implementing CoYourClass etc. ]
В другом месте в памяти (один экземпляр этого для всех объектов класса):
[ (12 bytes) vtable for CoYourClass::IUnknown ]
[ (28 bytes) vtable for CoYourClass::IDispatch ]
[ (4*n bytes) vtable for CoYourClass::IMyInterface ] <---- (*pInterface) points here
Записи в таблице vtable указывают на thunks. Когда вы вызываете pInterface->Foo();
, извлекается запись vtable, соответствующая Foo
, которая является кодовым адресом thunk. Этот thunk получает pInterface
в качестве указателя this
. Thunk знает, что это IMyInterface thunk в классе CoYourClass и в этом случае вычитает фиксированное смещение 8
байт, чтобы получить указатель на начало объекта. Затем thunk вызывает фактический код, который вы написали, для реализации Foo
, передавая скорректированный указатель как this
.
Примечание к OP: вы можете выяснить, какой формат использует ваш компилятор, проверив память и переменные в вашем отладчике при вызове объекта (проще всего, если ваш отладчик позволяет вам перейти от кода клиента в код сервера для процесса объект)
'Должен быть какой-то способ конвертировать из интерфейса в указатель класса' Почему это должно быть? Насколько вам известно, COM-объект реализован, скажем, в Visual Basic, и нет такого понятия, как «класс» за ним. Как вы думаете, для чего вам нужна эта информация? Какую проблему ты пытаешься решить? –