Über die Unverträglichkeit von Interfaces und dynamic_cast
Die Probleme der C++-Umsetzung von COM-Interfaces.
Moritz Beutel, 31.10.2008
- dynamic_cast<> mit C++-Klassen
- COM in C++
- dynamic_cast<> mit Delphi-Klassen
- Ein pragmatischer Workaround
- Referenzen
- Kommentare
COM-Interface-SpezifikationLayout-Anforderungen:Nicht mehr, nicht weniger.
dynamic_cast<> mit C++-Klassen
Was passiert also, wenn dynamic_cast<> auf ein Interface appliziert wird?
IMyInterface* intf = createObject ();
MyClass* mc = dynamic_cast <MyClass*> (intf);
void __far * DEFCC __DynamicCast(void __far * objectPtr,
void __far * vtablePtr,
void __far * srctypPtr,
void __far * dsttypPtr,
int reference); eine Compiler-Optionnegative Offsets der VMTHenry Spencer stellte vollkommen zutreffend fest: "If you lie to the compiler, it will get its revenge."
COM in C++class IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE QueryInterface (REFIID riid, void **ppvObject) = 0;
virtual ULONG STDMETHODCALLTYPE AddRef (void) = 0;
virtual ULONG STDMETHODCALLTYPE Release (void) = 0;
};
typedef struct _IUnknownVtbl
{
HRESULT (STDMETHODCALLTYPE * QueryInterface) (
IUnknown* This,
REFIID riid,
void** ppvObject);
ULONG (STDMETHODCALLTYPE * AddRef) (
IUnknown* This);
ULONG (STDMETHODCALLTYPE * Release) (
IUnknown* This);
} IUnknownVtbl;
struct IUnknown
{
const IUnknownVtbl* lpVtbl;
};
dynamic_cast<> mit Delphi-Klassen darlegte, ist das VMT-Layout einer Delphi-Klasse anders als das einer C++-Klasse:
void *__fastcall _EXPFUNC __DynamicCastVCLref(void *ptr, void *targetVMT);
void *__fastcall _EXPFUNC __DynamicCastVCLptr(void *ptr, void *targetVMT);
Ein pragmatischer Workaroundclass __declspec(uuid("{22807D4C-1770-472D-A44B-4D87B53D0189}")) MySelfAwareClass
: public MyCppClass
{
virtual HRESULT STDMETHODCALLTYPE QueryInterface (REFIID riid, void **ppvObject)
{
DO_QUERYINTERFACE (MySelfAwareClass)
return MyCppClass::QueryInterface (riid, ppvObject);
}
};
int _tmain (void)
{
_di_IUnknown i = new MySelfAwareClass;
MySelfAwareClass* msac;
i->QueryInterface (__uuidof (MySelfAwareClass),
reinterpret_cast <void**> (&msac));
}
Referenzen
[1] Der Quelltext der Runtime-Libraries von Delphi und C++Builder (in C++Builder enthalten)
[2] Raymond Chen, The layout of a COM object, 05.02.2004
[3] The C++ Standards Committee, State of C++ Evolution (Post-Antipolis 2008 Mailing), 30.06.2008
Kommentare
Deprecated: mysql_connect(): The mysql extension is deprecated and will be removed in the future: use mysqli or PDO instead in /www/htdocs/w008ab83/ad/phputils/dbc_mysql.php on line 112
|